当前位置: 首页 > news >正文

Spring 是如何解决循环依赖的

在这里插入图片描述

1. 场景设定 —— “A和B互相日”

  • A依赖BB也依赖A,两个SB在XML或注解里勾搭上了。
  • 问题:Spring先造A还是先造B?不管先造谁,对方都他妈没出生,死循环!

2. 三级缓存到底是哪三级?
Spring内部有三个Map(缓存池),专门处理这种死锁:

  1. singletonFactories(一级缓存,工厂池):存的是半成品对象工厂(对象刚new出来,还没填属性)。
  2. earlySingletonObjects(二级缓存,半成品池):存从工厂池里拿到的半成品对象(可能被代理过)。
  3. singletonObjects(三级缓存,成品池):存完全初始化好的成品单例对象

口诀
“一厂二半三成品,对象升级靠缓存”


3. 解决流程 —— “套娃式创建”
以A和B互相依赖为例(假设都是单例,用属性注入):

  • Step1: 开始创建A

    1. 用反射无脑new A() → 此时A是个空壳(属性全null)。
    2. 把A的对象工厂(一个能返回A的lambda)扔进一级缓存(singletonFactories)。
    • 此时A的状态:半残次品(没属性,但工厂已注册)。
  • Step2: 给A填充属性B

    1. Spring发现A依赖B → 去成品池(三级缓存)找B → 没有!
    2. 开始创建B:同样反射new B() → B也是个空壳。
    3. 把B的工厂扔进一级缓存
  • Step3: 给B填充属性A

    1. B需要A → 先去成品池找A → 没有!
    2. 二级缓存找 → 也没有!
    3. 关键骚操作:从一级缓存(工厂池)找到A的工厂 → 调用getObject(),拿到A的半成品对象(此时A还是空壳)。
    4. 把A的半成品扔进二级缓存(防止重复创建),同时从一级缓存移除A的工厂
    5. 把A的半成品塞给B → B完成属性填充,变成成品B
    6. 把B扔进三级缓存(成品池),清空B在一级、二级的缓存。
  • Step4: 回头完善A

    1. 此时B已经是成品,A拿到B的成品,填充自己的属性 → A变成成品。
    2. 把A从二级缓存升级到三级缓存,清空一级缓存。

最终结果
A和B都进了三级缓存(成品池),互相持有对方的成品引用,套娃成功!


4. 为什么构造函数循环依赖无解?

  • 关键区别:属性注入(setter/字段注入)是先创建空对象,再填属性;构造函数注入是创建对象时必须传参
  • 死锁场景
    1. 创建A → 必须传B(但B还没创建)→ 去创建B。
    2. 创建B → 必须传A(A还没创建完)→ 死循环。
  • Spring直接摆烂:抛出BeanCurrentlyInCreationException,并骂你代码写得像屎。

5. 动态代理的坑 —— “AOP代理搅局”

  • 如果A被AOP代理(比如用了@Transactional),半成品A和最终A可能不是同一个对象
  • 解决方案
    1. 一级缓存存的是对象工厂ObjectFactory),而不是对象本身。
    2. 工厂的getObject()会判断是否需要代理 → 确保半成品和成品对象类型一致(要么都是原生对象,要么都是代理对象)。
  • 核心骚操作:工厂生产对象时动态套娃,保证AOP代理只被创建一次。

总结
三级缓存的本质是“先交差,再补锅”——允许半成品对象临时被引用,后续再完善。
就像你老板催你交PPT,你先给个草稿(半成品),等同事给你数据(依赖)后再补全终稿(成品)!

相关文章:

  • 火山引擎旗下防御有哪些
  • 东方博宜OJ ——2395 - 部分背包问题
  • 游戏引擎学习第228天
  • Mysql的查询
  • 2021-10-29 C++按天数返回年月日,按年月日求第几天。
  • Android 项目 Camera 问题:Fail to connect to camera service
  • std::condition_variable的使用说明(详细解释和使用示例)
  • YOLOv3损失函数与训练模块的源码解析
  • Web:Swagger 生成文档后与前端的对接
  • rebase master后会将master的commit历史加入这个分支吗
  • bat脚本执行完后自动删除
  • 第七讲、在Isaaclab中使用交互式场景
  • 微信小程序腾讯获得所在城市
  • Python multiprocessing模块Pool类介绍
  • DeepReaserch写的文献综述示例分享
  • 【Kubernetes基础--Pod深入理解】--查阅笔记2
  • vmcore分析锁问题实例(x86-64)
  • 站台候车,好奇铁道旁的碎石(道砟)为何总是黄色的?
  • Spark-SQL核心编程2
  • redis 内存中放哪些数据?
  • 同济研究生开发AI二维码走红拿下大奖,新一代00开发者掀起AI创业潮
  • 长三角主流媒体将走进“来电”宜昌,探寻高质量发展密码
  • 解读丨连续两日施压,特朗普为何着急让美联储降息
  • 观察|如何推动再保险交易规模上量增加话语权,行业在临港新片区共倡议
  • 江苏银行去年净赚超318亿增超10%,不良贷款率持平
  • 新高!足金饰品报价每克破千元