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

SpringBoot使用@RequiredArgsConstructor遇循环依赖错误的解决及原因咨询

解决Spring Boot构造器注入循环依赖问题及原理分析

我来帮你拆解这个问题,先搞明白为什么两种注入方式在循环依赖上表现不同,再给你靠谱的解决办法。

一、为什么字段注入能处理循环依赖,构造器注入却不行?

Spring处理循环依赖靠的是三级缓存机制,但这个机制只对「实例化后再注入依赖」的方式生效,而字段注入和构造器注入的执行时机完全不同:

  • 字段注入的流程是:先调用Bean的无参构造器创建一个「半成品实例」,把这个半成品放到缓存里,之后再通过反射给字段赋值。比如你的A和B例子:

    1. Spring先创建A的半成品实例(无参构造),放进缓存;
    2. 准备给A注入B,于是去创建B的半成品实例(无参构造),也放进缓存;
    3. 给B注入A时,直接从缓存里拿到A的半成品,完成B的初始化;
    4. 回到A的注入流程,拿到初始化完成的B,完成A的初始化。
      整个过程因为有半成品缓存,循环依赖能被化解。
  • 构造器注入的流程是:Bean的实例化必须依赖构造器参数的实例。比如A的构造器需要B,B的构造器需要A:

    1. Spring尝试创建A,发现需要B的实例;
    2. 转而创建B,发现需要A的实例;
    3. 这时候A还没实例化完成(因为构造器没执行完,没放进缓存),B也等不到A,直接触发循环依赖报错。
      本质是构造器注入要求「依赖必须完全就绪才能实例化Bean」,而三级缓存救不了这种“先有鸡还是先有蛋”的死锁。

二、解决构造器注入循环依赖的方案

1. 优先重构代码(最推荐)

循环依赖通常是代码设计不合理的信号——两个Service互相依赖,说明它们的职责边界可能模糊了。比如把A和B都依赖的逻辑抽成一个独立的C Service,让A和B都依赖C,彻底打破循环。这是从根源解决问题的方式,能让代码结构更清晰。

2. 使用@Lazy延迟注入

在其中一个依赖上添加@Lazy注解,Spring会给这个依赖生成一个代理对象,构造Bean的时候注入的是代理,真正调用该依赖的方法时才会初始化目标Bean。比如:

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DomandaDocumentoService {
    private final DomandaDocumentoRepository domandaDocumentoRepository;
    // 给循环依赖的Service加上@Lazy
    private final @Lazy DomandaDatoBeneficiarioService domandaDatoBeneficiarioService;
    // 其他依赖...
}

这样构造DomandaDocumentoService时,DomandaDatoBeneficiarioService会以代理形式注入,不会触发其立即初始化,等到实际调用它的方法时,DomandaDocumentoService已经完成初始化,就能正常获取依赖了。

3. 改用Setter注入(应急方案)

把其中一个Service的构造器依赖改成Setter注入,让Spring先实例化半成品Bean,再通过Setter注入依赖:

@Service
public class A {
    private B b;

    @Autowired
    public void setB(B b) {
        this.b = b;
    }
}

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class B {
    private final A a;
}

这样A会先通过无参构造实例化并进入缓存,B的构造器可以拿到A的半成品实例完成初始化,之后Spring再调用A的Setter注入B,完成整个流程。

4. 临时退回到字段注入(不推荐)

虽然能解决问题,但字段注入的弊端很明显:依赖不明确(看构造器才知道依赖哪些Bean)、Bean不是不可变的、不利于单元测试,所以尽量只作为临时应急方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:32:33