SpringBoot学习笔记(三):EnableAutoConfiguration作用和机制

总结:

1、Spring Contex 和 Bean的解析和注册(@Configuration和@Import)

2、SpringFacotoriesLoader

3、@Conditional机制


一、EnableAutoConfiguration注解的本质是一个@Import

   import了一个EnableAutoConfigurationImportSelector,而@import注解是归属于@Configuration注解的

  所以这个注解应该是被@Configuration注解解析器来解析的


二、EnableAutoConfigurationImportSelector继承至DeferredImportSelector--->ImportedSelector

  1:ImportSelector接口,顾名思义,是对@Import注解的选择器

  2:接口方法返回一个配置列表,给@Configuration标注的Java Config类使用

  3:Configuration会递归处理调用所有的import配置

/**

* Select and return the names of which class(es) should be imported based on

* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.

*/
String[] selectImports(AnnotationMetadata importingClassMetadata);


三、Spring如何从@Configuration到@EnableAutoConfiguration

  1:SpringApplication为一些注解添加后置处理器:(注意,这里回到SpringFramework context框架中了,是Spring容器管理的通用框架和逻辑)

SpringApplication使用AnnotatedBeanDefinitionReader解析基于注解的Java配置,在AnnotatedBeanDefinitiaonReader构造方法中,AnnotationConfigUtils.registerAnnotationConfigProcessors(registry)为Java配置所使用到的注解添加后置处理器,其中有一个为ConfigurationClassPostProcessor

  2:调用链如下

找到所有的@Configuration类ConfigurationClassPostProcessor.processConfigBeanDefinitions()

 

  使用ConfigurationClassParser解析每个配置类:ConfigurationClassParser.parse()---> processConfigurationClass()--->      doProcessConfigurationClass()

 

  这个解析过程中,有一步是处理@import注解的:ConfigurationClassParser.processImports()


最后调用DeferredImportSelector.selectImports()接口方法:selector.selectImports(currentSourceClass.getMetadata())


DeferredImportSelector内部机制

public String[] selectImports(AnnotationMetadataannotationMetadata) {

//是否开启自动配置

if (!isEnabled(annotationMetadata)){

return NO_IMPORTS;

}

try {

//加载Spring内部自动配置的默认原属性

AutoConfigurationMetadataautoConfigurationMetadata=AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);

AnnotationAttributes attributes =getAttributes(annotationMetadata);

 

//加载需要被自动配置类,最关键的一个地方

//使用SpringFactoriesLoader,"EnableAutoConfiguration"作为key,加载META-INF/spring.factories中的值

List<String> configurations =getCandidateConfigurations(annotationMetadata,attributes);

configurations =removeDuplicates(configurations);

configurations =sort(configurations, autoConfigurationMetadata);

 

//去掉不要的自动配置类

Set<String> exclusions =getExclusions(annotationMetadata, attributes);

checkExcludedClasses(configurations,exclusions);

configurations.removeAll(exclusions);


//处理@Condition注解,内部还是使用spring.factories加载一个key为"AutoConfigurationImportFilter"的过滤器

//org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\

//org.springframework.boot.autoconfigure.condition.OnClassCondition

configurations =filter(configurations, autoConfigurationMetadata);

 

//发消息,给后续处理

//事件监听器还是通过SpringFactoriesLoader加载spring.factories中key为"AutoConfigurationImportListener"

//的所有监听器

fireAutoConfigurationImportEvents(configurations,exclusions);


//返还给ConfigurationClassParser继续处理

return configurations.toArray(newString[configurations.size()]);

}catch (IOException ex) {

throw newIllegalStateException(ex);

}

}


SpringLoaderFactories机制

SpringFactoriesLoader 会查询 META-INF/spring.factories文件
当找到
spring.factories 文件后,SpringFactoriesLoader 将使用key名,查找并返回

一个包含所需配置的列表List<String> configurations。

(EnableAutoConfiguration的spring.factories在spring-boot-autoconfigure包中)

这里我仅列出需要加载的自动配置,如下:

# 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.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\

....


六、结尾工作ConditionEvaluationReportAutoConfigurationImportListener
这里仅仅是report工作,--debug选项可以看到这个报告
@Override
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
if (this.beanFactory != null) {
ConditionEvaluationReport report = ConditionEvaluationReport
.get(this.beanFactory);
report.recordEvaluationCandidates(event.getCandidateConfigurations());
report.recordExclusions(event.getExclusions());
}
}


@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (beanFactory instanceof ConfigurableListableBeanFactory
? (ConfigurableListableBeanFactory) beanFactory : null);
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值