spring使用三级缓存解决循环依赖简介

循环依赖一般是指两个类中互相注入彼此,这种情况下如果两个类都要作为bean放到spring容器里,则都要进行bean的生命周期从而在执行属性填充(依赖注入)时就会报错,因为进入了死循环,好在spring使用了三级缓存解决了这个问题,

但如果是构造函数的注入即便是spring也不能解决。

在讲解spring如何解决相互依赖之前先了解这个三级缓存到底是什么,其实说到底这三级缓存就是三个map集合。

图中的singletonObjects就是一级缓存,一个初始化大小为256的ConcurrentHashMap,也是我们每次常说的spring容器(IOC容器,也叫单例池),里面存放的是经过完整bean生命周期的对象(也有可能是代理对象)。

图中的singletonFactories就是三级缓存,一个初始化大小为16的HashMap,它的value是一个lambda表达式,执行表达式里的getObject()方法就会返回一个对象(一个不完整的对象)

图中的earlySingletonObjects就是二级缓存,也是一个初始化大小为16的HashMap,它存放的是通过取出执行三级缓存中lambda表示调用getObject()方法之后得到的对象(就是把原来存在于三级缓存里的东西移入二级缓存)

这里再讲解springBean的生命周期:

实例化、属性填充、初始化、销毁

更具体点:class--->(在多构造函数情况下先推断使用哪个构造函数)实例化得到对象--->属性填充(依赖注入)--->初始化(通过实现接口或加注解执行某些方法给某些属性进行初始化赋值)---->可能需要AOP生成代理对象--->生成bean放入spring容器--->销毁

循环依赖,例如AService和Bservice互相注入,并且都是有特殊注解(@Component、@Service等)都要成为bean

如果先加载AService,先实例化生成对象,再进行属性填充,发现里面需要BService的bean,就去创建BService的bean,又到属性填充时发现需要AService的bean,这时就发生了相互依赖。

解决思路如下:

AService在实例化生成一个不完整对象时,把它放在三级缓存中(实际放入的不是对象而是一个lambda表达式,执行表达式才能得到对象),发现依赖BService的bean,先去一级缓存里面找,发现找不到,就又去二级缓存里面找,

发现又找不到,再去三级缓存里面找还是找不到,就去创建BService的bean从而又开始了BService的bean生命周期,同样先实例化得到对象放到三级缓存,在属性填充时发现依赖AService的bean,就去一级缓存里面找,发现找不到,

又去二级缓存里面找,也找不到就去三级缓存里面找,找到了前面AService放到三级缓存里面的lambda表达式,执行表达式得到对象并放到二级缓存里面同时删除三级缓存里面的AService的lambda,如下图所示。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值