删除@Autowired解决Spring循环依赖后,需确认影响及使用场景
问题背景
团队合并代码后,在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>
疑问
- 修改后是否会产生功能、性能等方面的影响?
- 在该场景及未来开发中,何时应使用
@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

