Spring 中循环依赖的类如何初始化

前言:面试中之前问过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

参考:
1 理解Spring循环引用(循环依赖)
2 Spring framework读书笔记

你可能感兴趣的:(Spring 中循环依赖的类如何初始化)