问题
如果有两个AutoConfiguration, 他们的@ConditionalOnMissingBean都是同一个Bean,那么谁会注册到这个bean呢?
解答
AutoConfigurationImportSelector是SpringBoot自动装配的核心,里面对所有AutoConfiguration进行了排序
- 按命名升序
- 再按
@AutoConfigureOrder升序 - 最后按
@AutoConfigureAfter,@AutoConfigureBefore调整顺序
验证
由于FirstMissingAutoConfiguration的命名排序比SecondMissingAutoConfiguration先,所以first注册
但是前者的@AutoConfigureOrder大于后者,所以second先
最后前者@AutoConfigureBefore于后者,所以first先注册
@Test
public void autoConfigTest() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(FirstMissingAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(SecondMissingAutoConfiguration.class))
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
.run((context) -> {
assertThat(context).getBean("first").isNotNull();
assertThat(context).getBean("second").isNull();
});
}
@Configuration
@AutoConfigureOrder(2)
@AutoConfigureBefore(SecondMissingAutoConfiguration.class)
public static class FirstMissingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Missing first() {
return new Missing();
}
}
@Configuration
@AutoConfigureOrder(1)
public static class SecondMissingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Missing second() {
return new Missing();
}
}
public static class Missing {
}
补充
You need to be very careful about the order in which bean definitions are added, as these conditions are evaluated based on what has been processed so far. For this reason, we recommend using only
@ConditionalOnBeanand@ConditionalOnMissingBeanannotations on auto-configuration classes (since these are guaranteed to load after any user-defined bean definitions have been added).
springboot官方文档有一句这样的话, Bean Conditions基于目前的bean定义来判断, 因为AutoConfiguration能保证在用户定义bean后加载,所以建议@ConditionalOnBean and @ConditionalOnMissingBean只用在AutoConfiguration