You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中@Bean注解抽象工厂方法仅实例化单个Bean问题咨询

问题根本原因

该现象是Spring的@Bean默认命名规则 + Bean定义覆盖默认策略共同导致的,具体逻辑如下:

  1. @Bean注解确实支持继承:父类A抽象方法上标注的@Bean会被子类B、C的实现方法继承,两个重写后的createService方法都会被Spring识别为Bean工厂方法,你这部分的初始认知完全正确。
  2. 两个Bean的默认名称完全重复:Spring默认会将@Bean修饰的方法名作为Bean的注册名称,由于你必须重写父类的抽象方法,两个子类的方法名只能是createService,因此两个Bean的默认注册名都是createService。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 06:45:01