短篇的文字很难讲清楚,周瑜大大的讲解视频
https://www.bilibili.com/video/BV1xZ4y1G7fv?p=20

为什么会存在循环依赖

spring在bean生成时,会将依赖属性一起注入。注入时发现要注入的bean没有生成,会将对注入bean进行生成。
此时如果两个bean互相依赖,则会相互循环调用生成bean的操作,而注入一直无法成功。
本质上来说是bean生成不是原子过程,生成的过程中间步骤存在递归调用,出现相互循环递归的问题。

怎么解决相互循环递归的问题
增加外部的记录,递归中可以根据外部记录跳出循环递归。

spring的操作

一级缓存 singletonObjects

这个缓存的作用是单例bean生成后放入该map中,目的在于使单例bean不会重复生成,在bean生成方法中会先到一级缓存拿,拿到即直接返回。

二级缓存 earlySingletonObjects

这里是早期bean的map,在bean生成时,实例化了对象但还未完成注入操作,将该早期bean放到二级缓存中, 其它bean进行注入操作时会去二级缓存中查找,找到即注入。
这样操作的目的是为了解决循环依赖,在递归之前将早期bean放入了二级缓存,从而防止循环递归的问题。
在bean生成后期会将二级缓存中的早期bean完善,同时将bean移动到一级缓存中。

三级缓存singletonFactories

在aop的场景下存在一个问题,因为aop会将切面织入重新生成代理对象,原始对象被抛弃,真正使用到的是这个代理对象。
这里就要想办法让注入的对象是这个代理对象。
解决方案是将aop进行提前。
bean在生成时一开始将aop需要的内容缓存在 singletonFactories 中,在注入bean中发现是循环依赖则调用bean对应的aop工厂将aop完成。

但这里还有一个问题,多个bean都循环依赖了同一个bean,会存在一个bean多次aop成不同的代理对象的问题。此时再加一个外部map,earlyProxyReferences,发生过aop的bean记录下来,以避免多次aop的问题。