最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【全球速看料】【Spring】三级缓存解决循环依赖问题

来源:博客园

1、什么是循环依赖

顾名思义“循环依赖”,举一个简单的例子A中依赖B,B中依赖A,在实例化对象过程中,填充属性阶段A需要B对象,就去创建B对象,创建B对象的时候,发现B依赖了A,于是又去创建A对象,但此时A对象又没有创建结束,一级缓存中找不到,于是线程又去创建一个新的A对象,如此一来,就出现了重复创建的现象,最终会导致内存溢出,JVM报错终止。

2、解决方案


(相关资料图)

直接说Spring的解决方案:使用三级缓存。

设想1:若A、B均为普通对象(这里买下代理对象的伏笔),其实来2级缓存就能解决循环依赖,A提前吧自己的早期对象放到二级缓存中即可

设想2:若涉及到AOP切面代理的场景,就会有问题,你想,当A创建的时候,把早期A放入2级缓存(这时候AOP还没进行,放入2级缓存的还是原始对象),但是到了B创建的时候,去2级缓存中虽然能找到A的早期对象,但我们都知道,按理说B应该找到A的代理增强对象才对,所以就引出了3级缓存

三级缓存解决设想2:A创建的时候,把自己的早期工厂对象(你可以想象这个对象有一个getObject方法,可以拿到代理对象)放入三级缓存,后面B创建的时候直接去三级缓存拿这个早期工厂对象,get到之后(若是正常对象拿到的就是正常对象,若是被代理了这里拿到的就是代理对象),直接放到二级缓存,B直接拿二级缓存中的A早期代理对象即可,这样B创建完成,顺理成章A也能创建完成。到此循环依赖解决。

3、再说三级缓存原理

首先我们还是进行实例化A对象,这个时候,我们要将A的ObjectFactory对象放入Map3中。同样的继续进行属性填充,这个时候B还没创建,于是去创建B。

那么去实例化B的过程中,我们也是一样的,先把B的ObjectFactory放入Map了中。将B对象放入Map2中。

继续执行到B的属性填充,去获取A对象,而此时Map1中没有A,因为A还没有创建完成,我们则发现Map了中 有A的ObjectFactory对象,那么我们通过ObjeatFactory对象获取A的早期对象,然后將这个早期对象放入Map2中,同时删除Map3中的A,然后我们将A的引用给了B,那么同样的B对象这个时候也已经完整了。 接下来我们再把B放入Map中接下来从Map3中删除B。这时候B已经创建完成,A继续执行b的属性填充可以拿到B对象,这样A也完成,最后我们把A对象也放入了Map,删除掉Map2中的A。于是我们的储环依赖就此解决。

关键词: