spring 如何解决循环依赖
Spring 中使用了三级缓存的设计,来解决单例模式下的属性循环依赖问题。
解决的只是单例模式下 setter 方法注入bean属性循环依赖问题,
对于多例 Bean 和 构造方法注入 参数的循环依赖问题,并不能使用三级缓存设计解决。
缓存变化过程
- A实例化后、注入前放到3级缓存
- A在注入属性时,发现有循环依赖,因此需要先getBean(B),实例化B,并将B也 从入3级缓存
- B放到3级缓存后,这时B要开始注入属性A,于是B找到了循环依赖A后,再从头执行getBean(A)方 法,getSingleton方法本次从缓存中取,然后将A设置到2级缓存,并且从3级缓存移除。
- B如愿以偿的拿到了A完成注入,然后B执行到DefaultSingletonBeanRegistry#addSingleton方 法,将B从3级缓存移出,放入1级缓存,到此B完成。B的完成是被动的,A需要它,才会先去创建 它
- A 还要继续自己的流程,然后populateBean方法将B注入。然后,A移出2级缓存,进入1级缓存, 整个流程完成!
为什么不能解决非单例、构造方法的循环依赖问题
为什么不能解决构造方法的循环依赖?
创建对象会走构造方法,而构造方法的参数是互相依赖的对象,此时都还没有初始化创建完成,因此无法进行实例化创建
为什么不能解决多例的循环依赖?
IoC容器只会管理单例Bean,并将单例Bean存入缓存。作用域为prototype时,每次getBean 都会创建新的对象,并不存入缓存,因此不可以解决循环依赖问题。
解决方法
避免循环依赖:
引入第三个类C, A 和 B 都依赖 C, 而不是相互依赖