首页 >文档 > spring解决循环依赖的原理

spring解决循环依赖的原理

Spring解决循环依赖的原理是Java面试高频考点,通过三级缓存机制巧妙处理单例Bean的相互依赖问题。一级缓存存储完整Bean,二级缓存存放半成品引用,三级缓存保存Bean工厂对象。当Bean A依赖B时,Spring会先暂存A的半成品到三级缓存,待B创建时通过缓存获取A的引用,从而打破循环。需要注意的是构造器注入和原型Bean的循环依赖无法解决。掌握这一机制不仅能应对面试,更能深入理解Spring IoC容器的工作流程,帮助开发者处理复杂依赖关系。

Spring解决循环依赖的原理 - 面试高频题解析

作为一名Java开发者,在面试中被问及 Spring循环依赖 的原理是家常便饭。很多同学对这个概念一知半解,今天我们就以面试口述的形式,深入浅出地聊聊 Spring循环依赖 的核心解决机制。

🔥 2025最新Java面试宝典领取(限时福利):
<font color="blue">链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g 提取码: 9b3g</font>


🔍 一、什么是循环依赖?

简单说,就是两个或多个Bean互相引用对方,形成了“鸡生蛋蛋生鸡”的死锁局面。比如:

@Service
public class AService {
    @Autowired
    private BService bService; // A 依赖 B
}

@Service
public class BService {
    @Autowired
    private AService aService; // B 又依赖 A

这种 循环依赖 场景在单例模式下,如果处理不当会导致容器启动失败。


🧠 二、Spring三级缓存:破解循环依赖的关键

Spring通过 三级缓存 机制巧妙解决了单例Bean的 循环依赖 问题。这三个缓存容器分别是:

  1. singletonObjects(一级缓存)
    存放 完全初始化 好的Bean实例。成品仓库。

  2. earlySingletonObjects(二级缓存)
    存放 提前暴露 的半成品Bean(仅实例化,未填充属性)。过渡区。

  3. singletonFactories(三级缓存)
    存放 Bean工厂对象ObjectFactory),用于动态创建代理对象。生产线。

Spring三级缓存机制


⚙️ 三、Spring解决循环依赖的流程拆解

假设A和B发生循环依赖,Spring容器启动时是这样处理的:

  1. 创建A实例(半成品)

    • 调用A的构造器 new AService()
    • 将A的工厂对象放入 三级缓存singletonFactories
  2. 填充A的属性(发现依赖B)

    • 尝试从容器获取B实例
    • B尚未创建 → 触发B的实例化流程
  3. 创建B实例(半成品)

    • 调用B的构造器 new BService()
    • 将B的工厂对象放入 三级缓存
  4. 填充B的属性(发现依赖A!)

    • 尝试获取A实例:
      • 一级缓存? ✘
      • 二级缓存? ✘
      • 三级缓存 ✔ → 通过工厂提前暴露A的引用(可能是原始对象或代理)
      • 将A放入 二级缓存,清空三级缓存
  5. 完成B的初始化

    • B成功注入A的引用(半成品)
    • B成为完整Bean → 移入 一级缓存
  6. 继续初始化A

    • 从一级缓存获取B的成品 → 注入A
    • A完成初始化 → 移入 一级缓存

经过这个过程,A和B这对互相依赖的对象成功完成初始化,循环依赖 被完美解决。


⚠️ 四、关键注意事项

  1. 只支持单例模式
    原型Bean(prototype)的循环依赖会直接抛出 BeanCurrentlyInCreationException

  2. 构造器循环依赖无解
    如果依赖通过构造器注入(而非Setter),三级缓存机制失效:

    public AService(BService bService) {...} // 构造器依赖
    

    此时Spring会检测到死循环并报错。

  3. AOP代理的特殊处理
    如果Bean需要被代理(如AOP切面),Spring会通过 SmartInstantiationAwareBeanPostProcessor 在三级缓存中提前生成代理对象(如下图流程):

Spring代理与循环依赖


💡 面试应答技巧

当面试官问:“Spring如何解决循环依赖?” 可以这样回答:

“Spring通过三级缓存机制解决单例Bean的循环依赖问题。核心是提前暴露半成品Bean:

  1. 一级缓存放成品Bean;
  2. 二级缓存放提前暴露的引用(防重复代理);
  3. 三级缓存存生成Bean的工厂。
    当Bean A依赖B时,会先暂存A的半成品到三级缓存,等B创建时就能从缓存拿到A的引用。
    注意构造器注入的循环依赖无法解决,原型Bean也不行。”

🉐 小贴士:需要系统刷Java面试题的同学,推荐通过 面试鸭返利网 购买面试鸭会员,可返利25元!海量真题解析和项目难点剖析一网打尽👇
面试鸭返利活动


理解 Spring循环依赖 的解决原理,不仅能应对面试,更能加深对IoC容器工作流程的掌握。遇到复杂依赖关系时,你就能快速定位问题根源。

如果你想获取更多关于面试鸭的优惠信息,可以访问面试鸭返利网面试鸭优惠网,了解最新的优惠活动和返利政策。

🎯 立即加入面试鸭会员 →

扫码联系我返利
(当前返利8元,金额随官方实际价格波动,最好提前咨询)

面试鸭返利网客服-面试鸭返利网

面试鸭小程序码

面试鸭小程序码 - 面试鸭返利网

美团大额优惠券,给自己加个鸡腿吧!

美团大额优惠券,给自己加个鸡腿吧!

今日有支付宝大红包赶快领,手慢无

支付宝红包二维码

支付宝扫码领取1-8元无门槛红包

支付宝红包二维码