Spring如何解决循环依赖

*爱你&永不变心* 提交于 2020-04-05 19:38:45

1.什么是循坏依赖
 即循环引用,两个或多个bean相互引用,最终形成一个环。如图:

 
 
循环依赖图.png

2.什么是循环调用
 循环调用是方法之间的环调用。循环调用无法解决,除非有终结条件,否则就是死循环,最终导致内存溢出错误。

3.构造器循环依赖
 3.1 循环依赖过程
定义类依赖:

  Class A{
        private B b;
        A(B b){
              this.b = b;
         }
   }

   Class B{
          private C c;
          B(C c){
              this.c = c;
          }
   }

   Class C{
          private A a;
          C(A a){
                this.a = a;
           }
    }

JVM创建对象过程 如下图所示:

 
 
对象创建过程图.png

3.2 Spring解决构造器循环依赖
 无法解决通过构造器注入构成的循环依赖,只能抛出BeanCurrentylyInCreationException异常表示循环依赖。
 Spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”中,bean表示符在创建过程中将一直保持在这个池中,因此,如果在创建bean过程中发现自己已经在“当前创建bean池”中,将抛出BeanCurrentylyInCreationException异常,表示循环依赖;对于创建完毕的bean,将从“当前创建bean池”中清除掉。

4.setter循环依赖
 通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的。通过提前暴露一个单例工厂方法,从而使其他bean能够引用到该bean。
 注:只能解决单例作用域的bean循环依赖。
 具体步骤:
 (1)Spring容器创建单例 a bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将 “a”标识符放到“当前创建bean池”,然后进行setter注入b;
 (2)Spring容器创建单例 b bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将 “b”标识符放到“当前创建bean池”,然后进行setter注入c;
 (3)Spring容器创建单例 c bean,首先根据无参构造器创建bean,并暴露一个“ObjectFactory”,用于返回一个提前暴露一个创建中的bean,并将 “c”标识符放到“当前创建bean池”,然后进行setter注入a;进行注入"a"时,由于提前暴露了“ObjectFactory”工厂,从而使用它返回提前暴露一个创建中的bean。
 (4)最后在依赖注入“b”和“a”,完成setter注入。


 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!