SpringBoot:自动装配提速设计

名词约定:

配置类:指使用了@Configuration、@Component、@ComponentScan、@Import、@ImportResource、@Bean的类

 

SpringBoot的设计思想就是通过一个配置类导入多个项目范围内适用的配置类到spring容器里。单个配置类封装成ConfigurationClass对象后,它的处理过程如图:

通常,如果一个配置类的元标注含有Import标注,解析这个配置类时,程序就会进入ConfigurationClassParser#processImports方法。Import标注指定的类会带出一些候选的配置类,然后将它们封装成SourceClass的集合。这个集合将成为processImports方法 的参数。

程序会轮循SourceClass集合的每个元素,如果该元素实现了ImportSelector接口、DeferredImportSelector接口,那么该元素将会带出更多的候选配置类,然后将它们封装成另一个SourceClass集合,接着递归调用ConfigurationClassParser#processImports方法;如果该元素并非接口实现类,则将被视为候选的配置类递归地调用ConfigurationClassParser#processConfigurationClass方法。ConfigurationClassParser#processConfigurationClass方法通过ConditionEvaluator#shouldSkip方法判断是否需要进行解析,如果符合条件,则当作配置类继续进行解析;如果不符合条件,则停止当前候选配置类的解析。ConditionEvaluator#shouldSkip方法会检查候选配置类使用@Conditional标注的情况,使用相应的条件类来判断是否符合该条件的标准。这些条件类包括:OnClassCondition、OnBeanCondition、OnPropertyCondition等。

我们再抽象地看等这个过程。判断一个候选配置类,如果属于配置类,就解析这个配置类,解析中发现使用了@Import标,就会挨个地执行上述流程,然后如果新的配置类也使用了@Import标注,又会挨个地执行上述流程。。。。程序就是这样一直递归下去。直到被引入的配置类不再使用@Import标注。所以程序的处理过程有可能很漫长的。SpringBoot因此对自动装配做了优化设计,通过提前处理,减少引入的候选配置类数据,这样后续的递归就少很多工作量了。

SpringBoot的自动装配功能以EnableAutoConfiguration标注为特征。它的元标注@Import指定了AutoConfigurationImportSelector.class。此类实现了DeferredImportSelector接口,这接口是ImportSelector的子接口,因此该类存在引入更多候选类的方法"selectImports"。该方法最终会调用SpringFactoriesLoader#loadSpringFactories方法,loadSpringFactories会找到META-INF/spring.factories文件,并且以EnableAutoConfiguration的完整类名为key,找到对应的一大堆的候选配置类。这些类有的也使用了@Import标注,则意味着程序程序又要递归处理了。比如CloudAutoConfiguration这个类就使用了@Import标注。

我们再以CloudAutoConfiguration为例,它虽然使用了@Import标注,但同时使用了@ConditionalOnClass标注,而该标注指定CloudScanConfiguration.class,说明当虚拟机能够加载CloudScanConfiguration.class类文件时,CloudAutoConfiguration才能够作为候选配置类,如果虚拟机未能成功加载CloudScanConfiguration.class类文件时,不但CloudAutoConfiguration不会成为候选配置类,它打算引入的更多的候选配置类也将不会被处理。但是,判断CloudAutoConfiguration的时机点正常来说是从processImports方法递归调用processConfigurationClass方法,然后通过ConditionEvaluator#shouldSkip方法判断此候选配置类符不符合条件。

AutoConfigurationImportSelector#selectImports方法的优化设计是这样的,用配置文件(META-INF/spring-autoconfigure-metadata.properties)记录下自动装配涵盖的类,将每个候选类的完整类名加“.ConditionalOnClass”为key,它所依赖的类的全类名为value。以CloudAutoConfiguration为例就是org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration.ConditionalOnClass=org.springframework.cloud.config.java.CloudScanConfiguration。通过OnClassCondition对象来判断CloudScanConfiguration是否可以加载到虚拟机。如果加载不到,CloudAutoConfiguration就不会成为AutoConfigurationImportSelector#selectImports返回结果集的元素了。这样就不用等到递归调用processConfigurationClass方法再去判断是否符合条件了。

我们再审视下这个优化机制。仅仅是针对使用了@ConditionalOnClass标注的配置类进行优化。该标注的元标注是@Conditional,它指定的条件类是OnClassCondition。由这个条件类去判断@ConditionalOnClass指定的类能否被加载到虚拟机。

在我们平时的开发过程中,为某个配置类加上@EnableAutoConfiguration标注,并且工程导入CloudScanConfiguration所在的jar包,这个模块的配置类将被加载到spring,否则就不会加载。这个过程由上文的描述得以优化提速。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值