728x90
자동 구성 클래스와 빈 설계
@MyAutoConfiguration
@ConditionalMyOnClass("org.springframework.jdbc.core.JdbcOperations")
@EnableMyConfigurationProperties(MyDataSourceProperties.class)
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@ConditionalMyOnClass("com.zaxxer.hikari.HikariDataSource")
@ConditionalOnMissingBean
DataSource hikariDataSource(MyDataSourceProperties properties) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(properties.getDriverClassName());
dataSource.setJdbcUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
@Bean
@ConditionalOnMissingBean
DataSource dataSource(MyDataSourceProperties properties) throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass((Class<? extends Driver>) Class.forName(properties.getDriverClassName()));
dataSource.setUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
@Bean
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean
JdbcTransactionManager jdbcTransactionManager(DataSource dataSource) {
return new JdbcTransactionManager(dataSource);
}
}
@EnableMyConfigurationProperties 를활용해서 저번처럼 인자로 주입받은 클래스를 @Import를 통해 내부적으로 빈으로 등록하게 된다.
@ConditionalOnMissingBean을 통해서 같은 Datasouce 빈이 여러번 생성되는것을 방지한다.
@ConditionalOnSingleCandidate 를 통해서 주입받은 클래스가 한개만 빈으로 존재할떄 실행되게 만든다.
@MyConfigurationProperties(prefix = "data")
public class MyDataSourceProperties {
@MyAutoConfiguration
public class PropertyPostProcessorConfig {
@Bean BeanPostProcessor propertyPostProcessor(Environment env) {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
MyConfigurationProperties annotation = findAnnotation(bean.getClass(), MyConfigurationProperties.class);
if (annotation == null) return bean;
Map<String, Object> attrs = getAnnotationAttributes(annotation);
String prefix = (String) attrs.get("prefix");
return Binder.get(env).bindOrCreate(prefix, bean.getClass());
}
};
}
}
그러면 빈으로 등록되고 나서 저번에 등록한 BeanPostProcessor에서 @MyConfigurationProperties annotation을 확인하고 application.properties에 쓰인 정보와 mapping 해서 채워넣어준다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = HellobootApplication.class)
@TestPropertySource("classpath:/application.properties")
@Transactional
public @interface HellobootTest {
}
@HellobootTest
public class DataSourceTest {
@Autowired DataSource dataSource;
@Test
void connect() throws SQLException {
Connection connection = dataSource.getConnection();
connection.close();
}
}
@ExtendWith(SpringExtension.class) = spring container를 활용할 수 있게 해준다.
@ContextConfiguration = 인자로 준 HellobootApplication을 통해 모든 빈들을 만들 정보들을 가져오게된다. coponent scan을 통해 다 긁어모은다.
test시 @TestPropertySource를 통해 어떤 properties를 참고하여 MyDatasource 빈을 만들어야하는지 알려줘야한다.
728x90
'WEB > Spring Boot' 카테고리의 다른 글
웹 서버와 서블릿 컨테이너 (0) | 2023.05.08 |
---|---|
스프링 부트 자세히 살펴보기 (0) | 2023.02.14 |
외부 설정을 이용한 자동 구성 (0) | 2023.02.13 |
자동 구성 기반 애플리케이션 + 조건부 자동 구성 (0) | 2023.02.09 |
독립 실행형 서블릿 애플리케이션 (0) | 2023.02.02 |