【HBZ分享】循环依赖解决方案-Spring三级缓存

三级缓存的数据结构

  1. 三个级别的缓存都是Map结构
  2. 查找顺序会先从一级缓存开始找,没找到会走二级缓存,最后查三级缓存
  3. 技巧:三级缓存中保存的都是没有被查找过的对象,因为查找到三级缓存一定会调用getSingleton()方法, 而调用这个方法的时候就会将其移动到二级缓存。注意: 三级缓存中保存的都是没被查找过的对象,但是没被查找过的对应不一定都在三级缓存里,也有可能在一级缓存

三级缓存的作用

  1. 一级缓存SingletonObjects: 存放完整可直接提供给外部使用的对象,完全成熟
  2. 二级缓存EarlySingletonObjects: 存放还未填充属性的对象,可以认为只是个空壳子,主要作用解决循环依赖
  3. 三级缓存SingletonFactories: 工厂刚出炉的对象,可以认为还处于在工厂中的阶段,依然是个空壳子, 调用完构造方法后,就会将对象放到三级缓存,主要作用解决循环依赖

对象何时从三级缓存移动到二级缓存,与一级缓存的?

  1. 当调用getSingleton()方法的时候,会移动到二级缓存,此时二级缓存会add(), 而三级缓存会调用remove()。
  2. 时机:当A,B两个对象相互依赖,A对象实例化完毕后会放到3级缓存,此时依赖注入需要立即创建B对象,B对象注入A对象时,就会从三级缓存找到A,此时会调用getSingleton(), 也是这个时候,A对象会从三级缓存移出进入到二级缓存。
  3. 当对象已竟完整的被创建后,会add()到一级缓存,然后remove()掉二级和三级缓存

扩展: Spring如何解决循环依赖的流程

  1. 前提: A,B两个对象相互依赖。
  2. 创建A对象时,实例化完毕,即调用构造方法完毕时会将A这个不成熟的空壳子对象放到三级缓存中
  3. 紧接着会依赖注入,此时发现自己需要B对象,所以会从一级缓存开始找B对象,直至找到第三级缓存,此时B对象肯定不在三级缓存中。
  4. 没找到B对象会立即去创建B对象,创建B对象时依然会走同样的创建流程,先实例化,然后依赖注入。
  5. 当B对象进行依赖注入时,发现自己需要A对象,所以会调用getSingleton()方法,从一级缓存开始找A。当然最终会在三级缓存中找到,因为A实例化后就放到三级缓存了。
  6. B在三级缓存找到A对象后,会将A对象添加到二级缓存,然后remove()掉三级缓存里面的A对象。
  7. 至此为止,B完成了依赖注入,然后开始初始化,初始化完毕后会将B对象放到一级缓存,然后remove()掉二级缓存里面的B对象,B对象此时创建完成。
  8. 回头再重新对A对象进行依赖注入,此时A对象从一级缓存就能直接找到B对象进行依赖注入了,然后A开始初始化,最终完成bean创建

扩展2: 什么样的循环依赖Spring无法解决?

  1. 循环依赖在构造方法中,此时Spring无法解决这类循环依赖,因为创建bean依靠的就是无参构造方法。换句大白话就是A还没进入三级缓存,就要产生了循环依赖,这就完了
  2. 多例的场景下无法解决循环依赖,三级缓存解决的场景一定是单例情况下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值