如何在Spring Boot应用配置中依赖自定义Starter模块中的Bean?
这个问题其实是Spring Boot配置加载顺序导致的——你说得没错,应用自身的@Configuration类确实会比自定义Starter里的自动配置类先被处理。所以当Spring尝试创建MyApplicationBean的时候,Starter里的MyFeatureConfiguration还没被初始化,这时候用@ConditionalOnBean自然检测不到它。
给你几个可行的解决方案,按简单程度排序:
方案一:让应用配置类在自动配置之后处理
最直接的方式是用@AutoConfigureAfter注解指定你的应用配置类要在Starter的自动配置类之后处理。这样Spring会先完成MyAutoConfiguration的Bean创建逻辑,再处理你的ApplicationConfig,这时候@ConditionalOnBean就能正确检测到MyFeatureConfiguration了。
修改后的ApplicationConfig代码如下:
@Configuration @AutoConfigureAfter(MyAutoConfiguration.class) class ApplicationConfig { @Bean @ConditionalOnBean(MyFeatureConfiguration.class) public MyApplicationBean myService(MyFeatureConfiguration config) { return new MyApplicationBean(config); } }
方案二:复用Starter的配置条件
既然MyFeatureConfiguration的创建依赖于my.feature前缀的配置属性,那你可以直接在MyApplicationBean的Bean方法上复用同一个@ConditionalOnProperty条件。这样只要Starter的Bean能被创建,你的应用Bean也会跟着被创建,不需要关心加载顺序的问题:
@Configuration class ApplicationConfig { @Bean @ConditionalOnProperty(prefix = "my.feature") public MyApplicationBean myService(MyFeatureConfiguration config) { return new MyApplicationBean(config); } }
这种方式的好处是和Starter的触发条件完全绑定,不会因为加载顺序或者其他配置变更导致不一致。
方案三:调整自动配置的加载顺序(进阶)
如果你的Starter需要被优先处理,也可以在MyAutoConfiguration上加上@AutoConfigureOrder注解,设置一个比默认值更小的数值(默认是0,数值越小越先处理):
@Configuration @EnableConfigurationProperties(MyProperty.class) @AutoConfigureOrder(-10) public class MyAutoConfiguration { // 原有代码不变 }
不过这种方式不如前两种直观,除非你有特殊的多Starter顺序依赖需求,否则不推荐优先用这个。
额外说明
这里再强调下核心原因:Spring Boot启动时,会先扫描应用包下的所有@Configuration类并解析,之后才会通过spring.factories里的EnableAutoConfiguration导入自动配置类。所以默认情况下,应用配置的Bean定义会先被处理,这时候自动配置的Bean还不存在,导致@ConditionalOnBean失效。上面的方案本质上都是通过调整顺序或者绑定条件来解决这个时间差问题。
备注:内容来源于stack exchange,提问作者migucm

