首页 > 编程语言 > 详细

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

时间:2021-08-06 10:40:09      阅读:11      评论:0      收藏:0      [点我收藏+]

循环依赖一般是指两个类中互相注入彼此,这种情况下如果两个类都要作为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,如下图所示。

技术分享图片

 

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

原文:https://www.cnblogs.com/attachment-1900/p/15106497.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!