Files
blog/src/content/posts/Java/Spring/如何解决循环依赖.md
meowrain 7b7e32ddd4
Some checks failed
Clean ESA Versions on Main / clean-esa-versions (push) Has been cancelled
init
2026-01-02 00:03:49 +08:00

4.0 KiB
Raw Blame History

title, published, description, image, tags, category, draft, lang
title published description image tags category draft lang
Spring如何解决循环依赖 2025-09-16
Spring
循环依赖
Java
Java > Spring false

Spring如何解决循环依赖

关键是提前暴露未完全创建完毕的Bean Spring中采用了三级缓存解决了循环依赖

我们拿下面这个例子来讲

@Service
public class A {
    @Autowired
    private B b;
}

@Service
public class B {
    @Autowired
    private A a;
}

//或者自己依赖自己
@Service
public class A {
    @Autowired
    private A a;
}

首先要创建Bean A,去一级缓存里面找,发现没有,二级缓存里面找,发现也没有,三级里面也没有 这个时候进入Bean A 的对象创建流程

接下来我们利用反射创建对象A调用其无参构造方法创建一个对象A 的实例并将其包装成ObjectFactory放入三级缓存中。

接下来要填充属性

因为A对象的属性是B对象

所以现在要开始创建Bean B 到一级二级三级缓存中找B对象发现不存在所以进入B对象的创建流程

依然是通过反射调用B的无参构造方法创建B的实例并将其包装成ObjectFactory放入三级缓存中。

接下来要填充B对象的属性就又要进入Bean A的创建流程中再去缓存中查找A对象我们能发现在三级缓存中已经有A的ObjectFactory了

可以从源码中看到我们会调用存放在三级缓存中A的ObjectFactory的getObject方法创建单例对象存放在earlySingletonObjects里面二级缓存然后从三级缓存中移除A的ObjectFactory

好的这样的话我们就可以把A填充到B对象需要的属性里面了

我们看看缓存转移的关键源码 第一步先把B的完整对象放到一级缓存中然后从三级缓存中移除B的ObjectFactory再从二级缓存中移除B当然二级缓存中也没有B接下来完成B的单例注册。这样缓存转移就完成了。

这样就完成了B对象的初始化

但是我们B对象的创建流程是在A对象的填充属性流程里所以会继续A的填充属性流程这个时候再去一级缓存里找B就能找到B了填充B并进行缓存转移移除二级三级缓存中的A对象就可以注入B完成A初始化了

三级缓存的作用

为了AOP

当Spring没有循环依赖的情况下是把普通对象创建好后再生成代理对象Spring也没有办法提前知道对象之间的依赖关系。也不能把每个对象都创建出代理对象来所以就需要把对象包装成objectFactory这个类型通过其中的ObjectFactory对象中的getObject方法获取到生成的代理对象。