别盲从了,spring 解决循环依赖真的一定需要三级缓存吗?demo结合源码讲解三级缓存的真正目的,一级缓存singletonFactories的真正作用,看到文章最后让面试官眼前一亮

文章详细探讨了Spring框架中的三级缓存机制,特别是在处理循环依赖和AOP代理时的作用。通过示例代码和流程图解释了singletonFactories如何在循环依赖时提供对象工厂,以及在有无AOP代理的情况下如何保持对象创建周期的规则。一级缓存存放对象工厂,二级缓存存放提前曝光的循环依赖对象,三级缓存的存在是为了在不影响大多数bean生命周期规则的前提下,有效地处理小概率的循环依赖和AOP代理问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

本篇是我上一篇《3分钟秒懂,最简单通俗易懂的spring bean 生命周期介绍与源码分析,附上demo完整源码》姊妹篇

spring 三级缓存问题是面试中的热点问题,大部分回答者会说是为了解决循环依赖问题 有的面试官可能会继续深究,会问那么换成2级缓存不可以吗,singletonFactories
这级缓存具体作用是什么呢,这时候你会如何回答呢?
不卖关子,实际上二级缓存就是可以解决循环依赖问题的,那么为什么还要多一个singletonFactories 的以及緩存呢


我们本篇結合源码查看一下具体为什么需要加一层singletonFactories

demo实现循环依赖

首先我们创建两个互相依赖的类teacher和student,并且创建student的aop代理 ,源码如下:

teacher 源码
在这里插入图片描述

student 源码

在这里插入图片描述

aspect 代理类
在这里插入图片描述

三级缓存解决循环依赖整体流程图

我这画的有点小了,大家方法查看

在这里插入图片描述

三级缓存解决循环依赖流程描述

1.首先初始化student 将自己的factory 放入一级缓存singletonFactories
2.注入teacher 依赖,发现teacher 中有student 依赖
3.断定student为循环依赖,所以执行student的factory 创建对象
3.1 如果对象是aop代理 则getEarlyBeanReference 返回代理对象
3.2 如果对象是正常对象,则直接返回该对象
4. teacher 注入student 的半成本对象,完成注入,初始化完成,teacher 放入成品赤
5. student 完成teacher 注入,初始化完成,student 放入成品吃


结合源码查看代码执行流程

首先是执行doCreateBean 初始化student

在这里插入图片描述

放入对象的factory到一级缓存

在这里插入图片描述
在这里插入图片描述

注入依赖teacher

在这里插入图片描述

注入teacher的依赖student ,发现student 是循环依赖

调用student 的factory获取对象实例

在这里插入图片描述

如果是有aop代理,则直接返回代理对象
在这里插入图片描述
在这里插入图片描述

student 注入完成,teacher初始化完成,放入成品池

在这里插入图片描述

teacher 注入完成,student初始化完成,放入成品池

在这里插入图片描述

初始化完成


思考:spring 为什么要用三级缓存而不是二级缓存(亮点)

我们从源码可以看到,一级缓存singletonFactories 放入的是对象工厂 二级缓存是放入循环依赖时的提前曝光对象
如果去掉一级缓存,直接将二级缓存作为循环依赖时的半成品池,实际上依然可以解决循环依赖问题
可以创建对象就放入二级缓存,不管是循环依赖还是普通注入,最后都可以完成并放入成品池中 那么为什么spring 要使用一级缓存呢
spring 有的类是需要aop代理的,但是我们如果只有二级缓存的情况下
那么流程就得变为每次创建对象的时候都得判断是否有代理,有的话创建代理,然后进行依赖注入 这样就违背了spring
的对象创建原则(既先注入,然后实例化,最后生成代理类) 为了解决这个问题,spring
特意添加了一级缓存,而且一级缓存放入的不是具体的实例,而是一个factory
这样就可以在只有发生循环依赖的情况下才会打破规则(提前创建代理类) 调用 getEarlyBeanReference
这个时候内部wrapIfNecessary再去判断是否是需要生成代理类 如果是需要代理,则创建代理类返回
如果是普通类,则直接返回对应bean 所以归根结底,spring 这样做得目的就是为了最小限度的保留他的bean的创建周期规则
不希望因为小概率的循环依赖aop代理就完全从头开始打破这个规则


通过上面分析我们可以了解,实际上singletonFactories 这个得作用就是在循环依赖出现的情况下,
没有代理时正常返回对象本身,有aop代理情况下直接返回代理,这样就可以最大程度的位置spring
的后置创建代理,不希望因为小概率的循环依赖aop代理就完全从头开始打破这个规则(先依赖注入->创建对象->创建代理对象)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峡谷电光马仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值