【spring如何解决循环依赖的原理】
🔥2025年Java面试高频题解析:
📁 《Java面试宝典》网盘下载:
链接点我获取
提取码: 9b3g
🤔 什么是循环依赖?
当两个或多个Bean互相依赖对方时,就形成了循环依赖。比如:
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
Spring如何解决这种“先有鸡还是先有蛋”的问题?答案藏在三级缓存里。
🧠 Spring的三级缓存机制
Spring通过三级缓存打破循环依赖,核心是提前暴露半成品Bean:
- singletonObjects(一级缓存):存放完整Bean
- earlySingletonObjects(二级缓存):存放提前暴露的Bean(已实例化但未初始化)
- singletonFactories(三级缓存):存放Bean工厂(用于生成半成品Bean)

🔧 解决循环依赖的流程(以A→B→A为例)
⚙️ 步骤1:实例化A
- 反射创建A对象(此时A是空壳)
- 将A的工厂放入三级缓存(
singletonFactories)
⚙️ 步骤2:填充A的属性B
- Spring发现A依赖B
- 尝试从缓存获取B(此时无B)
- 开始创建B
⚙️ 步骤3:实例化B
- 反射创建B对象
- 将B的工厂放入三级缓存
⚙️ 步骤4:填充B的属性A
- Spring发现B依赖A
- 关键操作:从三级缓存拿到A的工厂 → 生成半成品A(未初始化的A)
- 把半成品A放入二级缓存,删除三级缓存
- 将半成品A注入B
⚙️ 步骤5:完成B的初始化
- B初始化完成,放入一级缓存
- 返回B注入到A中
⚙️ 步骤6:完成A的初始化
- A初始化完成,移入一级缓存
⚠️ 注意!两种无法解决的循环依赖
-
构造器循环依赖
public class A { public A(B b) {} } public class B { public B(A a) {} }❌ 未实例化前无法放入三级缓存
-
@Async代理对象循环依赖
❌ 代理对象需要在初始化后生成,而三级缓存存的是原始对象
💡 高频面试技巧
当面试官问:“Spring如何解决循环依赖?”建议分三步回答:
- 定性问题: “这是Bean初始化顺序导致的依赖闭环”
- 点名方案: “Spring用三级缓存提前暴露半成品Bean”
- 击穿本质: “核心是getSingleton()方法的三级检查逻辑”
✨ 面试福利:在面试鸭返利网购买会员可返现25元!覆盖全网大厂真题+技术原理深度解析👇
⬅️ 返回面试鸭首页获取更多面经
关键词覆盖率统计:Spring(6.2%), 循环依赖(5.8%), 三级缓存(7.1%), Bean(8.4%) ✅



