SpringBoot中spring.factories指定的EnableAutoConfiguration并不是按照配置顺序执行 ! ! !
本文基于SpringBoot 2.6.4分析
先看示例:
@Configuration
public class DbAutoConfig {
public DbAutoConfig() { System.out.println("DbAutoConfig"); }
@Bean
public Bean1 dbBean() {
System.out.println("db bean");
return new Bean1();
}
}
@Configuration
public class RedisAutoConfig {
public RedisAutoConfig() { System.out.println("RedisAutoConfig"); }
@Bean
public Bean1 redisBean() {
System.out.println("redis bean");
return new Bean1();
}
}
在META-INF/spring.factories
中配置如下:
按照一开始的设想:由于RedisAutoConfig配置在DbAutoConfig的前面,所以redisBean应该在dbBean之前被创建 ?
然而这个设想是错误的,dbBean先被创建了,输出结果如下。
源码分析:
开始o.s.core.io.support.SpringFactoriesLoader#loadFactoryNames
确实是从spring.factories
按照顺序加载配置类保存在List
中,但是在执行o.s.boot.a.AutoConfigurationImportSelector.AutoConfigurationGroup#selectImports()
时会对这些配置类进行排序后再注册到Spring上下中
排序规则如下:
- 先按照配置类的全类名字符串进行排序
- 再按照配置类上的
@AutoConfigureOrder
注解排序 - 最后按照
@AutoConfigureBefore
@AutoConfigureAfter
两个注解排序
如上就是示例中为什么配置类不是按照在spring.factories
配置的顺序执行的原因!!!
针对这个问题,曾在2020年的时候给SpringBoot提过,希望按照在spring.factories
配置的顺序执行,但是被否决了,不过wilkinsona
的回复也是有一定道理的。所以我们知道就好 ! ! !
It is suggested that the key of EnableAutoConfiguration in spring.factories can be sorted
@AutoConfigureOrder
@AutoConfigureBefore
@AutoConfigureAfter
三个注解元数据是怎么读取的?
每个自动装配的配置类都会被封装在
org.springframework.boot.autoconfigure.AutoConfigurationSorter.AutoConfigurationClass
中,获取注解元数据时通过org.springframework.core.type.classreading.MetadataReaderFactory#getMetadataReader(java.lang.String className)
获取MetadataReader
来读取注解元数据,MetadataReader
实际上内部又使用ASM
框架读取字节码来实现。
spring.factories
中同一个key配置的value有重复时,是否会导致多个实例对象
当前看的这个版本org.springframework.core.io.support.SpringFactoriesLoader
在加载配置类时会去重,不会重复。但是低版本可能出现多个实例对象。
请看spring-framework的修复记录:Revise duplicate filtering in SpringFactoriesLoader