Spring三级缓存和循环依赖

1. 三级缓存概念

创建Bean的大概的过程:
1.实例化Bean对象,为Bean对象在内存中分配空间,各属性赋值为默认值
2.初始化Bean对象,为Bean对象填充属性
3.将Bean放入缓存

一级缓存

一个数据结构来存储,比如Map {k:name; v:bean},bean为完整bean(即初始化也实例化过的bean)
循环依赖会造成死循环
例:A对象依赖了一个B对象,而B对象内部又依赖了一个A

1.实例化A对象。
2.填充A的属性阶段时需要去填充B对象,而此时B对象还没有创建,所以这里为了完成A的填充就必须要先去创建B对象; 实例化B对象。
3.执行到B对象的填充属性阶段,又会需要去获取A对象,而此时Map中没有A,因为A还没有创建完成,导致又需要去创建A对象。
4.这样,就会循环往复,一直创建下去,只到堆栈溢出

为什么不能在实例化A之后就放入Map?

因为此时A尚未创建完整,所有属性都是默认值,并不是一个完整的对象,在执行业务时可能会抛出未知的异常。所以必须要在A创建完成之后才能放入Map。

二级缓存

二级缓存用另外一个Map2 {k:name; v:earlybean} 来存储尚未已经开始创建但是尚未完整创建的对象(只实例化没有初始化的bean)

解决循环依赖

1.实例化A对象之后,将A对象放入Map2中。
2.在填充A的属性阶段需要去填充B对象,而此时B对象还没有创建,所以这里为了完成A的填充就必须要先去创建B对象。
3.创建B对象的过程中,实例化B对象之后,将B对象放入Map2中。
4.执行到B对象填充属性阶段,又会需要去获取A对象,而此时Map中没有A,因为A还没有创建完成,但是我们继续从Map2中拿到尚未创建完毕的A的引用赋值给a字段。这样B对象其实就已经创建完整了,尽管B.a对象是一个还未创建完成的对象。
5.此时将B放入Map并且从Map2中删除。 这时候B创建完成,A继续执行b的属性填充可以拿到B对象,这样A也完成了创建。
6. 此时将A对象放入Map并从Map2中删除。

三级缓存

二级缓存已然解决了循环依赖问题,为什么还需要三级缓存?
我们可以看到使用两级缓存可以完美解决循环依赖的问题,但是Spring中还有另外一个问题需要解决,这就是初始化过程中的AOP实现。
AOP是Spring的重要功能,实现方式就是使用代理模式动态增强类的功能。

参考链接:https://blog.csdn.net/m0_69519298/article/details/124346383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值