Spring 怎么解决循环依赖的呢?
单例 Bean 初始化完成需要经历三步:实例化、属性赋值、初始化
注入就发生在第二步,属性赋值
一级缓存:存储的是完整创建好的单例bean对象
二级缓存:存储的是尚未完全创建好的单例bean对象。存放实例化完成的bean实例
三级缓存:单例bean的创建工厂,方便后面有机会创建代理对象
比如AB循环依赖
-
创建A实例,实例化的时候把A对象工厂放入三级缓存,表示A开始实例化了,虽然我这个对象还不完整,但是先曝光出来让大家知道
-
A属性赋值的时候,发现依赖B,此时B还没有被创建出来,所以实例化B
-
同样,B属性赋值的时候发现依赖A,他从缓存里面找A对象。依次从一级到三级缓存查询A,从三级缓存通过对象工厂的创建拿到半成品对象A,发现虽然A不完整,但是存在,把A放在二级缓存,删除三级缓存中的A,此时,B实例化并初始化完成,把B放入一级缓存。
- 如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象
-
接着A继续属性赋值,顺利从一级缓存拿到实例化初始化完成的B对象,A对象创建也完成。删除二级缓存中的A,同时把A放入一级缓存。
为什么要三级缓存?⼆级不⾏吗?
不行
如果对象A引用的对象B配置了AOP,则A就需要注入对象B的代理对象。就需要把B的代理对象创建出来,但是此时对象B处于实例化阶段,代理对象是要在对象B初始化完成之后的后置处理中生成的。所以需要三级缓存保存了生成对象的对象工厂,并没有存入实例化的对象,发生循环依赖的时候,利用对象工厂,提前进行AOP,生成动态代理对象。没有动态代理的时候,也可以返回普通对象。