Spring学习笔记01-解决循环依赖

A和B相互依赖,产生循环依赖问题:
        a对象注入b,b初始化需要注入a,此时a正在创建,由此形成循环依赖。

朴素的解决思路:
        引入一个 map(暂时命名myMap),该map记录半成品bean,然后a对象注入b时,发现b未创建,此时创建b,而创建时发现需要依赖a,那么此时不再直接创建a,而是去myMap中查找是否有a,如果有a则拿出。
        myMap中放的对象,其实就是半成品bean对象,其中的对象未经过AOP,也就不是AOP后产生的代理对象,而只是初步初始化出来的普通对象。

提前AOP:
        那么就有新的问题:如果a是一个引入了AOP的对象,那么b中引入a时,是从myMap中获取的未经过代理的普通对象,而不是a的代理对象,显然不符合正常要求。
综上,需要提前进行AOP,即在bean初始化前则进行AOP。


注:正常情况下AOP代理对象生成时间点: 是在bean初始化后,由BeanPostProcessor接口的postProcessAfterInitialization方法生成的。

整体解决循环依赖的流程如下:

一级缓存:singletonObjects
        主要存放最终完整的单例bean

二级缓存引入:earlySingletonObjects
        假设现在不仅有a和b相互依赖,a和c也相互依赖,根据以上的解决方法,有两条执行路径会先后进行:
(1)创建a -> 创建b -> 获取a半成品对象(半成品代理对象);
(2)创建a -> 创建c-> 获取a半成品对象(半成品代理对象);
        以上会生成两个a的半成品代理对象,出现冲突,因此需要在(1)执行时,记录入一个map中,然后(2)执行时,从这个map中取值,看是否存在,如果存在,则不执行,只使用已创建的a半成品代理对象,这个map就是二级缓存。
        因此,二级缓存主要作用:还是为了保证单例bean,只不过此时存储的是半成品bean对象,是个早期的单例bean对象,所以二级缓存在源码中称为earlySingletonObjects

三级缓存引入:singletonFactories
        以上一级二级缓存,其实并没有打破循环依赖,只是起到了对【单例】的控制,而打破循环依赖的关键点在于【生成半成品bean】,只有能生成bean,那么在这个bean被依赖时,才可以获取到,从而打破循环依赖。
        因此引入了三级缓存singletonFactories。
        只要bean是支持循环依赖且为单例的情况下,每个bean在创建过程中都会在三级缓存中加入相关内容,这个内容就是一个lambda表达式,是bean的factory,所以三级缓存命名为singletonFacotories。
        三级缓存未必都能用到,只有真的发生了循环依赖,二级缓存中未找到相应的半成品bean时,才会从三级缓存中取出lambda表达式并执行,执行后便产生半成品bean,然后将这个bean放入二级缓存,并在三级缓存中删除该bean对应的lambda表达式。

        附上一张经典图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值