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

删除@Autowired解决Spring循环依赖后,需确认影响及使用场景

循环依赖问题与Autowired使用疑问解答

问题背景

团队合并代码后,在SpringBootApplication类上添加@EnableFeignClients注解,并从主分支引入Feign客户端、配置等内容,启动应用时出现循环依赖错误:

The dependencies of some of the beans in the application context form a cycle: xxx

删除相关控制器/服务类中的@Autowired注解并将成员变量设为private后,应用可正常启动。

修改前代码

@Autowired
MyUtil myUtil; // @Component标记的Bean

@Autowired
MyConfig myConfig; // @Component标记的Bean

@Autowired
MyApi myApi; // Feign客户端接口

public void myFunction(){
   String id = myUtil.getId();
   String name = myConfig.getNameById(id);
   myApi.sendInfo(id, name); 
}

修改后代码

private MyUtil myUtil; // @Component标记的Bean

private MyConfig myConfig; // @Component标记的Bean

private MyApi myApi; // Feign客户端接口

public void myFunction(){
   String id = myUtil.getId();
   String name = myConfig.getNameById(id);
   myApi.sendInfo(id, name); 
}

Spring版本

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>

疑问

  1. 修改后是否会产生功能、性能等方面的影响?
  2. 在该场景及未来开发中,何时应使用@Autowired,何时无需使用?

解答

1. 修改后的影响分析

直接去掉@Autowired并把变量设为private,这些变量不会被Spring容器注入任何实例。当前应用能启动只是因为还没触发到调用myFunction()的逻辑,一旦执行到myUtil.getId()这类代码,必然会抛出NullPointerException空指针异常,功能直接失效。

启动不报错的原因是:原来的循环依赖是Spring在尝试注入这些Bean时产生的,现在你不让Spring处理这些依赖注入,它自然不会去解析依赖链条,循环依赖问题就“消失”了,但这属于掩耳盗铃的假解决方式,完全牺牲了功能。

性能方面没有影响,但功能完全无法正常工作,这是核心问题。

2. @Autowired的使用场景与正确姿势

必须用@Autowired的场景

只要你需要使用Spring容器托管的Bean实例(比如被@Component、@Service、@FeignClient等注解标记的类),就需要通过依赖注入获取实例——@Autowired是Spring提供的依赖注入方式之一。

无需用@Autowired的场景

只有当变量是你自己手动创建的普通对象(比如new MyUtil()),或者是常量、局部变量时,才不需要@Autowired。

解决当前循环依赖的正确方案

既然是引入Feign后出现的循环依赖,大概率是Feign客户端与现有服务/配置形成了依赖闭环,推荐以下几种方案:

  • 构造器注入(Spring官方推荐):将依赖通过构造器传入,不仅能避免空指针,还能让循环依赖问题更早暴露,也符合依赖倒置原则:
private final MyUtil myUtil;
private final MyConfig myConfig;
private final MyApi myApi;

// Spring会自动装配构造器参数
public YourServiceClass(MyUtil myUtil, MyConfig myConfig, MyApi myApi) {
    this.myUtil = myUtil;
    this.myConfig = myConfig;
    this.myApi = myApi;
}
  • @Lazy延迟注入:在循环依赖链条中的某一个依赖上添加@Lazy注解,让Spring延迟初始化该Bean,打破循环:
@Autowired
@Lazy
private MyApi myApi;
  • 重构代码拆解循环:梳理清楚依赖链条(比如A→B→C→A),把公共逻辑抽成独立的无依赖Bean,解开闭环。

内容的提问来源于stack exchange,提问作者St.Paramago

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:20:53