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

spring解决循环依赖的原理

Spring框架通过三级缓存机制巧妙解决循环依赖问题,包括Singleton Objects、EarlySingleton Objects和SingletonFactories三个层级。当ServiceA依赖ServiceB而ServiceB又依赖ServiceA时,Spring会先创建原始对象存入三级缓存,在属性注入阶段通过ObjectFactory获取早期引用,最终完成初始化。这种设计既支持单例模式下的循环依赖,又能正确处理AOP代理。需要注意的是构造器注入和原型模式无法使用该方案,开发中建议采用@Lazy注解或代码重构来优化依赖关系。理解Spring三级缓存原理是Java面试中的高频考点,也是实际开发中避免循环依赖问题的关键。

spring解决循环依赖的原理

面试鸭返利网

最近在准备Java面试的同学应该都听说过「循环依赖」这个高频考点。今天我们就来聊聊Spring框架如何通过三级缓存巧妙化解循环依赖的难题。

需要2025年最新Java面试资料的同学,可以下载这个面试宝典:
百度网盘链接 提取码: 9b3g


什么是循环依赖?

简单来说就是两个Bean互相依赖对方。比如ServiceA依赖ServiceB,ServiceB又依赖ServiceA。这种情况下,Spring如果直接创建Bean就会陷入死循环。


Spring的三级缓存结构

Spring通过三个Map结构(即三级缓存)解决这个问题:

  1. 一级缓存(Singleton Objects):存放完全初始化好的Bean
  2. 二级缓存(EarlySingleton Objects):存放刚实例化但未初始化的Bean
  3. 三级缓存(SingletonFactories):存放Bean工厂对象

面试鸭返利网


解决循环依赖的流程

我们以ServiceA和ServiceB的循环依赖为例:

  1. 创建ServiceA实例

    • 通过反射调用构造器创建原始对象
    • 将ServiceA的工厂对象放入三级缓存
  2. 填充ServiceA属性

    • 发现需要注入ServiceB
    • 开始创建ServiceB
  3. 创建ServiceB实例

    • 同样将ServiceB的工厂对象放入三级缓存
    • 填充属性时发现需要注入ServiceA
  4. 解决ServiceB的依赖

    • 从三级缓存拿到ServiceA的工厂对象
    • 执行getEarlyBeanReference()生成代理对象(如果需要AOP)
    • 将生成的ServiceA代理对象放入二级缓存
  5. 完成ServiceB初始化

    • ServiceB拿到ServiceA代理对象完成属性注入
    • 初始化后的ServiceB放入一级缓存
  6. 回填ServiceA属性

    • 将初始化好的ServiceB注入到ServiceA
    • 最终将ServiceA放入一级缓存

为什么必须三级缓存?

很多同学可能会问:能不能只用两级缓存?答案是不行!因为:

  • 二级缓存存放的是未完成初始化的Bean
  • 三级缓存通过ObjectFactory延迟处理AOP代理
    这种设计既保证了单例,又避免了重复代理的问题。

需要注意的坑

  1. 构造器注入无法解决循环依赖
  2. 原型模式(prototype)的Bean不支持循环依赖
  3. 多线程环境下要注意缓存访问顺序

面试鸭返利网


实战建议

在开发中如果遇到循环依赖,可以考虑以下方案:

  • 使用@Lazy延迟加载
  • 重构代码结构解耦
  • 优先使用setter注入而非构造器注入

需要购买面试鸭会员的同学注意啦!通过面试鸭返利网下单可返现25元,相当于用全网最低价获取海量面试真题解析。

掌握Spring循环依赖的原理,不仅能应对面试中的深度追问,更能帮助我们在实际开发中避免踩坑。记得结合Bean的生命周期来理解整个流程,这样记忆会更深刻!

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

🎯 立即加入面试鸭会员 →

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

支付宝红包二维码