升级Spring Boot 3.4后多Bean定义错误的排查与解决问询
解决Spring Boot 3.4中@Primary与@ConfigurationProperties共存导致的多Bean冲突问题
问题原因
Spring Boot 3.4的这项变更——Registered @ConfigurationProperties beans now respect @DependsOn, @Description, @Fallback, @Lazy, @Primary, @Scope and @Role annotations.——是冲突的核心:
- 3.4版本前,
@ConfigurationProperties仅作为配置绑定标记,不会单独生成Bean,仅为@Component注册的Bean绑定配置。 - 3.4版本后,
@ConfigurationProperties会触发自动注册一个独立Bean,且会继承类上的@Primary等注解。当类同时标注@Component、@Primary和@ConfigurationProperties时,会生成两个同类型Bean:@Component扫描生成的MyClassBean(带有@Primary标记)@ConfigurationProperties自动注册的fop.factory.pool-com.package.MyClassBean(同样继承@Primary)
两个Bean同时作为注入候选,最终触发“找到2个Bean”的启动错误。
解决方案
以下方式可解决冲突,同时保留@Primary和@ConfigurationProperties的原有功能:
方案一:用@ConfigurationPropertiesScan替代@Component
移除类上的@Component,保留@Primary和@ConfigurationProperties,通过启动类或配置类的@ConfigurationPropertiesScan扫描该类:
@Primary @ConfigurationProperties(prefix = "fop.factory.pool") public class MyClass { // 类内容 }
在启动类添加扫描注解:
@SpringBootApplication @ConfigurationPropertiesScan(basePackages = "com.package") public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
此方式让Spring仅通过配置属性机制生成一个带@Primary的Bean,避免重复注册。
方案二:用@EnableConfigurationProperties显式注册
同样移除@Component,在配置类中通过@EnableConfigurationProperties显式注册MyClass:
@Primary @ConfigurationProperties(prefix = "fop.factory.pool") public class MyClass { // 类内容 }
创建配置类:
@Configuration @EnableConfigurationProperties(MyClass.class) public class AppConfig { }
此方式仅生成一个由配置属性管理的Bean,同时保留@Primary的优先级标记。
方案三:指定@ConfigurationProperties的name属性(应急用)
若必须保留@Component,可给@ConfigurationProperties指定name属性,让自动生成的配置Bean与@Component的Bean同名,Spring会自动合并两个定义:
@Component @Primary @ConfigurationProperties(prefix = "fop.factory.pool", name = "myClass") public class MyClass { // 类内容 }
注意:此方式不如前两种规范,仅建议作为临时应急方案。
为什么不能直接移除注解
- 移除
@Primary:会导致其他依赖注入MyClass的地方出现多Bean候选错误(若存在其他同类型Bean)。 - 移除
@ConfigurationProperties:会失去配置前缀绑定功能,类无法读取fop.factory.pool开头的配置项。
内容的提问来源于stack exchange,提问作者Shi Lilian
相关产品推荐
相关产品推荐

