前言:面试中之前问过Spring 如果出现循环依赖的例子是如何初始化的,当时我的答案是不能初始化,估计面试官心理一万只cnm走过,哈哈。
- 循环引用
class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
class B {
private A a;
public B(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
就是在设计类的时候,对象A中的属性为对象B,对象B中的属性为对象A。两个对象互相引用。
- 需要了解的知识底点
1 Spring 依赖注入的方式有两种,属性注入和构造器注入,上边那个例子中A就是通过构造器注入的方式注入B中。
2 Spring中的bean根据作用域的不同,可以大体分为两类,singleton和prototype。singleton在一个容器中,只会有一个实例;而prototype在每次调用时,都会产生一个新的实例。
3 Spring中,单例bean有延迟加载和立即加载两种加载方式,其中立即加载模式会在容器启动的时候就创建bean,而延迟加载会在容器启动后,使用到bean的时候再加载它。本篇分析一律使用延迟加载,因为有时候单例bean的加载顺序,会影响到创建bean的成功或失败。
- 小结
- 当循环依赖的bean都是通过构造器注入依赖的时候,无论这些bean是singleton还是prototype,在获取bean的时候都会失败。
- 当循环依赖的bean都是通过属性注入依赖的时候,根据bean的作用域是singleton还是prototpye,会有不同的表现。
- 如果循环依赖的bean都是singleton,那么无论先获取哪个bean,都能成功。
- 如果循环依赖的bean都是prototype,那么无论先获取哪个bean,都会失败。
- 如果循环依赖的bean中有singleton,也有prototype,那么当先获取的那个bean是singleton时,就会成功,否则失败。
最终结论:如果多个bean存在循环依赖,在Spring容器启动后,只有当获取的第一个bean是通过属性注入依赖的singleton时,才会成功,别的情况都会失败。
具体分析见参考1,2
网友评论