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

Spring/Spring Boot中@Autowired能否注入@Bean声明的Bean

问题1:@Bean声明的Bean是否支持@Autowired注入

完全支持。@Bean注解声明的Bean和@Component/@Service等类注解标注生成的Bean,在Spring容器中没有本质区别,只要满足类型匹配、Qualifier名称对应,就可以被@Autowired正常注入,框架本身没有任何限制。
你之前给实现类加@Service、移除@Bean方法后注入正常,本质上只是换了一种Bean的注册方式,和@Bean注册的Bean注入规则完全一致。

问题2:当前代码循环依赖的产生原因

你遇到的循环依赖完全是代码写法导致的,和@Bean能不能被注入没有关系,初始化链路如下:

  1. 你的启动类SpringBootTestApplication被@SpringBootApplication标注(自带@Configuration元注解),本身就是容器需要初始化的一个配置类Bean
  2. 容器初始化这个配置类Bean时,发现它有字段注入的ServiceCaller依赖,于是暂停配置类的初始化,转而去创建ServiceCaller实例
  3. 创建ServiceCaller实例时,又发现它需要注入名为TestServiceInterfaceImplBean的TestServiceInterface类型Bean
  4. 这个Bean是定义在SpringBootTestApplication配置类里的@Bean方法,要执行这个方法生成对象,前提是SpringBootTestApplication这个配置类已经完成初始化
  5. 此时链路绕回起点:配置类没初始化完→拿不到ServiceCaller→ServiceCaller没初始化完→拿不到@Bean定义的TestService实例→拿不到TestService实例→配置类没法完成初始化,形成闭环循环,直接触发报错。

你之前把@Bean方法删掉、给实现类加@Service时不会报错,是因为这时候TestServiceInterfaceImpl是组件扫描直接识别的独立Bean,不需要依赖配置类的方法生成,初始化ServiceCaller时可以直接创建这个实现类实例,链路不会绕回未初始化完成的配置类,自然不会有循环。
额外说明:你main方法里手动创建AnnotationConfigApplicationContext的代码是多余的,SpringApplication.run本身就会创建并初始化容器,重复创建容器会导致不必要的资源浪费和初始化逻辑混乱,建议删掉。

问题3:修复方案
  • 方案1(推荐,符合Spring设计规范):不要在启动类/根配置类里写业务Bean的字段注入。启动类只保留启动逻辑,把ServiceCaller的注入和使用逻辑移到单独的业务组件或独立配置类中,从根源切断循环链路。
    修正后的启动类代码:
    @SpringBootApplication
    public class SpringBootTestApplication {    
       @Bean(name = "TestServiceInterfaceImplBean")
       TestServiceInterface getTestService() {
          return new TestServiceInterfaceImpl();
       }
    
       public static void main(String[] args) {     
          SpringApplication.run(SpringBootTestApplication.class, args);
       }
    }
    
  • 方案2:如果确实需要在启动类中持有ServiceCaller实例,把字段注入改成构造器注入,同时给依赖加@Lazy注解实现延迟加载,打破初始化的闭环:
    @SpringBootApplication
    public class SpringBootTestApplication {    
       private final ServiceCaller serviceCaller;
    
       @Bean(name = "TestServiceInterfaceImplBean")
       TestServiceInterface getTestService() {
          return new TestServiceInterfaceImpl();
       }
    
       public SpringBootTestApplication(@Lazy ServiceCaller serviceCaller) {
          this.serviceCaller = serviceCaller;
       }
    
       public static void main(String[] args) {     
          SpringApplication.run(SpringBootTestApplication.class, args);
       }
    }
    
  • 方案3(不推荐,仅做临时兼容):在application配置文件中添加配置spring.main.allow-circular-references=true,开启Spring默认关闭的循环依赖自动兜底机制。但这种方式会掩盖代码设计的不合理性,后续版本迭代很容易引发更难排查的问题,非紧急情况不建议使用。

内容的提问来源于stack exchange,提问作者SPL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:57:17