【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。于是我们的储环依赖就此解决。