Spring循环依赖(缩略版)
程序员文章站
2023-12-27 10:25:45
...
Spring循环依赖问题也算是个老掉牙的问题,一搜一大把,这里纯粹是为了给自己做个笔记,所以写(水)一篇博客
那么为什么要叫缩略版呢,因为这里不打算分析Spring源码来讲了(主要是因为懒),能画图那就不分析代码
首先Spring创建一个对象分为了三步:实例化 -> 填充属性 -> 初始化
那如果是在构造器中进行了循环依赖,假如A的构造器依赖于B,B的构造器中依赖于A,那么就类似于死锁了,Spring也救不了你
那么如果是使用setter方式的话呢?
@Component
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
@Component
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
}
那就不一样了,Spring默认构造的是对象单例,同时有三级缓存,singletonObjects(一级),earlySingletonObjects(二级),singletonFactories(三级),一级找不到就往下接着找,找到了的话就放入上一层中,这个应该很好理解吧
以上面的代码来画图说明一下setter方式是如何解决循环依赖的
简单解释一下图中的步骤
- A实例化完成,接着属性填充的时候找不到B,所以去执行B的实例化
- B实例化完成,属性填充的时候去找A
- 一二三级缓存依次往下找,因为A还未初始化完成,所以一二级缓存都找不到,在三级缓存中找到了还未初始化完成的A
- B完成属性填充和初始化,将自己加入到了一级缓存中
- A接着进行属性填充,获取到了B,接着进行初始化,A初始化完成,Spring循环依赖解决
总结:Spring如果是构造器构注入的话,无法解决循环依赖(这里的构造器注入说的是两个循环依赖的类都使用构造器注入,如果按照上面代码的顺序,A使用setter注入,B使用构造器注入的话,也是可以解决循环依赖的);如果是setter注入的话,依靠Spring的对象生成步骤和一二三级缓存的机制可解决循环依赖