在spring中, AutoConfiguration也是一个种Configuration,只是AutoConfiguration是不能使用proxy的。
而且spring对于两者的加载顺序也不是一视同仁,是有顺序的。spring会先加载@SpringBootApplication可达的且标注了@Configuration的类,这个过程会将@AutoConfiguration标注的类给过滤掉; 然后再通过spring spi加载AutoConfiguration,并且在这一过程中,会根据@AutoConfigureOrder, @AutoConfigureBefore, @AutoConfigureAfter这三个注解进行排序。
Configuration加载逻辑
springboot 处理ConfigBeanDefinition时,根据@SpringBootApplication注解处理Configuration和Bean的加载逻辑,处理逻辑其实就是一个Configuration类的解析逻辑,如下:
- 处理Component注解
- 如果MemberClass有标注@Component、@CompentScan、@Import、@ImportResource注解以及方法有标注@Bean注解,对MemberClass执行Configuration类的解析逻辑
- 处理PropertySources注解
- 处理ComponentScan
- 进行类扫描
- 指定扫描包路径下的类
- 过滤标有@AutoConfiugration注解的类
- 将扫描出来的类执行Configuration类的解析逻辑
- 进行类扫描
- 处理@Import
- 如果是ImportSelector类型,单独处理
- 如果ImportBeanDefinitionRegistrar类型,单独处理
- 否则执行类的Configuration类的解析逻辑
- 处理@ImportResource
- 将ConfigurationBean添加到LinkedHashMap中
- 执行ImportSelector
- 由于@SpringBootApplication注解标有@EnableAutoConfiguration,所以会执行org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
- 调用其内部类AutoConfigurationGroup的process()和selectImports()方法加载AutoConfiguration
- 由于@SpringBootApplication注解标有@EnableAutoConfiguration,所以会执行org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
执行截图如下:
从上面的逻辑可以看出,对于Configuration是无法有效管理其加载顺序,但是可以根据其加载逻辑通过@Import或者@ComponentScan等其它相关注解优化以解决非预期加载顺序的场景。
AutoConfiguration加载逻辑
- ConfigurationClassParser.parse()
- DeferredImportSelectorHandler.process()
- AutoConfigurationGroup.process()
- AutoConfigurationImportSelector.getAutoConfigurationEntry(): 获取到AutoConfiguration类信息列表后,去重、排除@EnableAutoConfiguration中的exclude、触发AutoConfigurationImportEvent
- ImportCandidates.load(): 从META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中获取AutoConfiguration类信息
- AutoConfigurationImportSelector.getAutoConfigurationEntry(): 获取到AutoConfiguration类信息列表后,去重、排除@EnableAutoConfiguration中的exclude、触发AutoConfigurationImportEvent
- AutoConfigurationGroup.selectImports()
- AutoConfigurationGroup.sortAutoConfigurations()
- AutoConfigurationSorter.getInPriorityOrder(): AutoConfiguration排序,可以通过@AutoConfigureOrder, @AutoConfigureBefore, @AutoConfigureAfter
- AutoConfigurationGroup.sortAutoConfigurations()
- AutoConfigurationGroup.process()
- DeferredImportSelectorHandler.process()
执行截图如下:
Bean的加载
接下是在Configuration是否满足条件,即执行Conditional条件判断,例@Conditonal, @ConditionalOnProperties等,如果不满足条件则略过Configuration。如果满足条件,则会继续加载Configration 中用于@Bean标注的方法。
对于Bean的加载逻辑也是一样会去判断Conditional,如果不符合加载条件则会略过,如果符合则会进行加载。
总结
- @SpringBootApplication可达的Configuration的加载要先于AutoConfiguration
- 对于Configuration加载顺序可以通过其加载机制使用@Import @ComponentScan等注解进行优化调整
- 对于AutoConfiguration的加载顺序可以通过@AutoConfigureOrder, @AutoConfigureBefore, @AutoConfigureAfter进行调整