@EnableAutoConfigurationAutoConfigurationSelectorConditional을 이용한 SpringBoot의 AutoConfiguration예제(JdbcTemplateAutoConfiguration)application.yaml의 property설정 예제 —DataSourceAutoConfiguration.java
- SpringBoot의 핵심은 AutoConfiguration에 있음. SpringBoot는 starter package들(spring-boot-starter-...)로 의존성 정해주고, bean 설정, property에 대한 것도 타입화 시켜놓고 자동화시켜놓음
- 특정 컨디션에 맞게끔 알아서 설정되도록 하는 기능이 막강한 기능임
@EnableAutoConfiguration

- @EnableAutoConfiguration 어노테이션으로 spring-boot-autoconfigure는 애플리케이션 클래스 로더를 사용해 META-INF/spring.factories 리소스 파일에서 메타데이터를 가져옴
- EnableAutoConfiguration에서 @Import(AutoConfigurationImportSelector.class) 이 부분이 실제로 AutoConfiguration을 해주는 다양한 AutoConfiguration 클래스들을 선택적으로 임포트하여 적용되도록 해줌
AutoConfigurationSelector
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); }
- 위의 코드 블럭에서 getCandidateConfigurations( ) 메서드를 부르면 아래 부분의 코드에서 spring.factories라는 파일을 참조해서 CandidateConfiguration들을 불러옴
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) { Map<String, List<String>> result = (Map)cache.get(classLoader); if (result != null) { return result; } else { HashMap result = new HashMap(); try { Enumeration urls = classLoader.getResources("META-INF/spring.factories");
Conditional을 이용한 SpringBoot의 AutoConfiguration예제(JdbcTemplateAutoConfiguration)
@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, JdbcTemplate.class }) @ConditionalOnSingleCandidate(DataSource.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) @EnableConfigurationProperties(JdbcProperties.class) @Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class }) public class JdbcTemplateAutoConfiguration { }
- 여기서 @ConditionalOnClass 어노테이션에 DataSource와 JdbcTemplate이 있는데, ConditionalOnClass는 classpath 에 해당하는 클래스들이 존재한다면(dependency에 해당 jar파일이 추가되어 있어야 한다!) JdbcTemplateAutoConfiguration이 동작하게 되는 것임
- ConditionalOnClass springboot가 제공해줌
- Import 부분에 Bean 등록정보가 있음.
@Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(JdbcOperations.class) class JdbcTemplateConfiguration { @Bean @Primary JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); JdbcProperties.Template template = properties.getTemplate(); jdbcTemplate.setFetchSize(template.getFetchSize()); jdbcTemplate.setMaxRows(template.getMaxRows()); if (template.getQueryTimeout() != null) { jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds()); } return jdbcTemplate; } }
- @ConditionalOnMissingBean(JdbcOperations.class) → JdbcOperations 이 빈으로 등록되어 있지 않을 때, 해당 class가 매치되어 JdbcTemplate( → JdbcOperations 구현함)이 빈으로 등록됨
application.yaml의 property설정 예제 —DataSourceAutoConfiguration.java
@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") @AutoConfigureBefore(SqlInitializationAutoConfiguration.class) @EnableConfigurationProperties(DataSourceProperties.class) @Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.InitializationSpecificCredentialsDataSourceInitializationConfiguration.class, DataSourceInitializationConfiguration.SharedCredentialsDataSourceInitializationConfiguration.class }) public class DataSourceAutoConfiguration {
- DataSourceProperties.class를 보면 이전에 배웠던 @ConfigurationProperties가 있음. 그래서, prefix를 이용하여 application.yaml의 property들을 자동으로 매핑해주어서 Autoconfiguration을 진행하는 것
@ConfigurationProperties(prefix = "spring.datasource") public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean { private ClassLoader classLoader; /** * Whether to generate a random datasource name. */ private boolean generateUniqueName = true; /** * Datasource name to use if "generate-unique-name" is false. Defaults to "testdb" * when using an embedded database, otherwise null. */ private String name; /** * Fully qualified name of the connection pool implementation to use. By default, it * is auto-detected from the classpath. */ private Class<? extends DataSource> type; /** * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. */ private String driverClassName; /** * JDBC URL of the database. */ private String url;