属性配置官网:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#common-application-properties
原理
@SpringBootApplication
spring主类必备注解,自动配置应该和它有关
点进@SpringBootApplication注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@EnableAutoConfiguration
发现里面有个@EnableAutoConfiguration注解(见名知义,启动自动配置),点进去
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@Import
又是派生注解,里面有一个注解@Import,指定了一个自动配置导入选择器AutoConfigurationImportSelector
下面研究一下这个自动配置选择器AutoConfigurationImportSelector类,有一个重写的selectImports 方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
// 获取自动配置项
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
- 点进getAutoConfigurationEntry 方法(根据名字推断是获取自动配置项)
/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param autoConfigurationMetadata the auto-configuration metadata
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(
AutoConfigurationMetadata autoConfigurationMetadata,
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 = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
根据注释
Return the AutoConfigurationImportSelector.AutoConfigurationEntry
based on the AnnotationMetadata of the importing @Configuration class.
可以获知
基于标注@Configuration注解的配置类的注解元数据返回自动配置项
点进getCandidateConfigurations 方法(根据名字是获取配置)
/**
* Return the auto-configuration class names that should be considered. By default
* this method will load candidates using {@link SpringFactoriesLoader} with
* {@link #getSpringFactoriesLoaderFactoryClass()}.
* @param metadata the source metadata
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
* attributes}
* @return a list of candidate configurations
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
// 扫描 META-INF/spring.factories,获取自动配置类全限定名称
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), 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;
}
根据注释
Return the auto-configuration class names that should be considered.
By default this method will load candidates using
SpringFactoriesLoader with getSpringFactoriesLoaderFactoryClass().
可以获知
是调用SpringFactoriesLoader.loadFactoryNames方法获取自动配置类全限定名称并返回结果
再根据代码
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.");
可以获知
自动配置类全限定名称是通过扫描 META-INF/spring.factories 获取
META-INF/spring.factories
查看 META-INF/spring.factories
可以发现文件内容格式是key = 用 “,” 隔开的value,如下
# 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,\
key: 启动自动配置类EnableAutoConfiguration的全类名org.springframework.boot.autoconfigure.EnableAutoConfiguration
value: 每个 “,” 分隔的都是一个自动配置类
流程
启动自动配置注解 @EnableAutoConfiguration 通过组合注解 @SpringBootApplication 标注在SpringBoot启动类上
@SpringBootApplication
public class Demo{
执行main方法,执行SpringApplication的run()方法
public static void main(String[] args) {
SpringApplication app = new SpringApplication(DistributeProceApp.class);
Environment env = app.run(args).getEnvironment();
}
内部执行selectImports() 方法,找到自动配置类的全限定名称,使用反射获取对应的class类,将所有配置类加载到Spring容器中,由此配置加载完成。
图示