Spring中@Bean注解抽象工厂方法仅实例化单个Bean问题咨询
问题根本原因
该现象是Spring的@Bean默认命名规则 + Bean定义覆盖默认策略共同导致的,具体逻辑如下:
@Bean注解确实支持继承:父类A抽象方法上标注的@Bean会被子类B、C的实现方法继承,两个重写后的createService方法都会被Spring识别为Bean工厂方法,你这部分的初始认知完全正确。- 两个Bean的默认名称完全重复:Spring默认会将
@Bean修饰的方法名作为Bean的注册名称,由于你必须重写父类的抽象方法,两个子类的方法名只能是createService,因此两个Bean的默认注册名都是createService。 - Spring默认的覆盖规则不会抛异常:传统Spring项目默认允许同名称Bean定义覆盖,Spring Boot 2.1+版本虽默认关闭了覆盖允许,但如果你的项目手动开启了该配置,后扫描到的Bean定义会直接覆盖先注册的同名称Bean,不会抛出冲突异常。你当前场景下B配置类比C先被Spring扫描到,因此C对应的F类型Bean定义直接被E覆盖,最终容器中仅存在名称为
createService的E实例。
解决方案
因为需要重写父类抽象方法无法修改方法名,所以只需要在子类重写方法上显式给@Bean指定不同的名称即可,示例如下:
@Configuration public class B extends A { // 显式指定Bean名称为eService @Bean("eService") @Override protected D createService() { return new E(); } } @Configuration public class C extends A { // 显式指定Bean名称为fService @Bean("fService") @Override protected D createService() { return new F(); } }
修改后容器中会同时存在eService(E类型)和fService(F类型)两个Bean,符合你的预期。
如果需要触发重复名称的异常提示,避免出现覆盖导致的隐性问题,可以在配置文件中添加配置:spring.main.allow-bean-definition-overriding=false
启动时就会抛出BeanDefinitionOverrideException,明确提示你存在同名称Bean定义冲突。
内容的提问来源于stack exchange,提问作者Ami
相关产品推荐
相关产品推荐

