自动配置
自动配置主要由 @EnableAutoConfiguration 实现,而 @SpringBootApplication 内复合了这个注解,因此被 @SpringBootApplication 的应用程序类就可以实现自动配置。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
可以看到这个注解 import 了 AutoConfigurationImportSelector 类,这个类中的 selectImports() 方法会通过调用 getAutoConfigurationEntry() 方法加载自动配置的配置项。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// 加载自动配置的配置项
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
getAutoConfigurationEntry() 方法会调用 getCandidateConfigurations() 方法,而 getCandidateConfigurations() 方法会通过 SpringFactoriesLoader 来加载配置,传入 EnableAutoConfiguration 的类。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
Spring Boot 提供的自动配置类位于 spring-boot-autoconfigure 包下的 spring.factories 文件中,截取部分如下,可以看到 Spring Boot 内置了很多自动配置的类。
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
我们以 DataSourceAutoConfiguration 类为例,这个类会自动配置 H2 数据源,具体看下面代码中的解析。
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
type = {"io.r2dbc.spi.ConnectionFactory"}
)
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})
public class DataSourceAutoConfiguration {
public DataSourceAutoConfiguration() {
}
// 重点解读一下这个Configuration, 它的具体功能是配置一个H2数据源
@Configuration(
proxyBeanMethods = false
)
// 带上 EmbeddedDatabaseCondition 类内定义的条件,满足条件时生效
@Conditional({DataSourceAutoConfiguration.EmbeddedDatabaseCondition.class})
// 容器内没有 DataSource 类型或者 XADataSource 类型的 bean 时才生效
@ConditionalOnMissingBean({DataSource.class, XADataSource.class})
// 导入 EmbeddedDataSourceConfiguration 类
@Import({EmbeddedDataSourceConfiguration.class})
protected static class EmbeddedDatabaseConfiguration {
protected EmbeddedDatabaseConfiguration() {
}
}
}
而 EmbeddedDataSourceConfiguration 这个内嵌数据库的配置则会创建一个类型为 EmbeddedDatabase 的 Bean。
@Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({DataSourceProperties.class})
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
private ClassLoader classLoader;
public EmbeddedDataSourceConfiguration() {
}
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
// 创建一个类型为 EmbeddedDatabase 的 Bean
@Bean(
destroyMethod = "shutdown"
)
public EmbeddedDatabase dataSource(DataSourceProperties properties) {
return (new EmbeddedDatabaseBuilder()).setType(EmbeddedDatabaseConnection.get(this.classLoader).getType()).setName(properties.determineDatabaseName()).build();
}
}
至此,整个H2数据源的Bean的创建过程结束。