spring如何解决循环依赖。相信大家都知道要通过三级缓存来解决,但具体的细节怎么样做的,可以一起来看一下。
问什么会产生循环依赖,这就得从IOC说起了
将对象交给容器控制,容器来创建对象,及其控制对象的生命周期。
容器在实例化对象后,要注入属性,注入属性A的时候,A需要B,注入B的时候,B又需要A,这就导致了循环依赖。
对于Bean的生命周期可以看这篇博客 Bean生命周期

那么分别用一级缓存和两级缓存会出现什么问题呢?
实例化A -> 将半成品的A放入singletonObjects中->填充A的属性时发现取不到B->实例化B->从singletonObjects中取出A填充B的属性->将成品B放入singletonObjects->将B填充到A的属性中->将成品A放入singletonObjects。
问题:这种基本流程是通的,但是如果在整个流程进行中,有另一个线程要来取A,那么有可能拿到的只是一个属性都为null的半成品A,这样就会有问题。
使用singletonObjects和earlySingletonObjects
成品放在singletonObjects中,半成品放在earlySingletonObjects中
流程可以这样走:实例化A ->将半成品的A放入earlySingletonObjects中 ->填充A的属性时发现取不到B->实例化B->将半成品的A放入earlySingletonObjects中->从earlySingletonObjects中取出A填充B的属性->将成品B放入singletonObjects,并从earlySingletonObjects中删除B->将B填充到A的属性中->将成品A放入singletonObjects并删除earlySingletonObjects。
问题:这样的流程是线程安全的,不过如果A上加个切面(AOP),这种做法就没法满足需求了,因为earlySingletonObjects中存放的都是原始对象,而我们需要注入的其实是A的代理对象。
因为切面时需要代理对象所以存在了三及缓存
三级缓存是用来存储代理Bean,当调用getBean()方法时,发现目标Bean需要通过代理工厂来创建,此时会将创建好的实例保存到三级缓存,最终也会将赋值好的Bean同步到一级缓存中。