spring循环依赖是怎么解决的?

面试官:spring循环依赖是怎么解决的?

回答:循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,好比CircleA引用CircleB,CircleB引用CircleA,则它们最终反映为一个环。
Spring如何解决循环依赖? 
假设场景以下,A->B->A 
一、实例化A,并将未注入属性的A暴露出去,即提早曝光给容器Wrap
二、开始为A注入属性,发现须要B,调用getBean(B)
三、实例化B,并注入属性,发现须要A的时候,从单例缓存中查找,没找到时继而从Wrap中查找,从而完成属性的注入
四、递归完毕以后回到A的实例化过程,A将B注入成功,并注入A的其余属性值,自此即完成了循环依赖的注入


spring中的循环依赖会有3种状况:
1.构造器循环依赖
    构造器的循环依赖是不能够解决的,spring容器将每个正在建立的bean标识符放在一个当前建立bean池中,在建立的过程一直在里面,若是在建立的过程当中发现已经存在这个池里面了,这时就会抛出异常表示循环依赖了。
2.setter循环依赖
   对于setter的循环依赖是经过spring容器提早暴露刚完成构造器注入,但并未完成其余步骤(如setter注入)的bean来完成的,并且只能决定单例做用域的bean循环依赖,经过提早暴露一个单例工厂方法,从而使其余的bean能引用到该bean.当你依赖到了该Bean而单例缓存里面有没有该Bean的时候就会调用该工厂方法生产Bean,
Spring是先将Bean对象实例化以后再设置对象属性的

Spring先是用构造实例化Bean对象,此时Spring会将这个实例化结束的对象放到一个Map中,而且Spring提供了获取这个未设置属性的实例化对象引用的方法。面试

为何不把Bean暴露出去,而是暴露个Factory呢?由于有些Bean是须要被代理的spring

3.prototype范围的依赖
对于“prototype”做用域bean,Spring容器没法完成依赖注入,由于“prototype”做用域的bean,Spring容器不进行缓存,所以没法提早暴露一个建立中的Bean。

 缓存