前言:
之前我们有分析过Spring是怎么解决循环引用的问题,主要思路就是三级缓存;Spring在加载beanA的时候会先调用默认的空构造函数(在没有指定构造函数实例化的前提下)得到一个空的实例引用对象,这个时候没有设置任何值,但是Spring会用缓存把它给提前暴露出来,让其他依赖beanA的bean可以持有它提前暴露的引用;比如 a 依赖b ,b依赖a,并且他们都是通过默认方法实例化,那么简单流程是这样的:
- ioc实例化a,a提前暴露自己的,然后填充属性值,在填充属性值的时候发现有个对象b,这个时候去容器里面取到b的引用,发现b还没有被创建,那么就走实例化b的流程;
- 实例化b;流程跟a一样;但是不同的是b填充属性的时候,发现有引用a的实例,这个时候a已经提前暴露了自己了,所以b可以直接在容器里面拿到a的引用;那么b就实例化并且也初始化完成了;
- 拿到b了之后,a就可以持有b的引用 ,整个流程就走完了;
Spring不能解决“A的构造方法中依赖了B的实例对象,同时B依赖了A的实例对象”这类问题
这篇文章我想从源码的角度来分析一下整个流程;并且分析一下Spring为什么不能解决“A的构造方法中依赖了B的实例对象,同时B依赖了A的实例对象”这类问题
例子
首先创建两个bean类; CirculationA 有个属性circulationB,并且有个构造函数给circulationB赋值;
public class CirculationA { private CirculationB circulationB; public CirculationA(CirculationB circulationB) { this.circulationB = circulationB; } } 复制代码
CirculationB有个属性circulationA,然后set方法
public class CirculationB { private CirculationA circulationA; public CirculationA getCirculationA() { return circulationA; } public void setCirculationA(CirculationA circulationA) { this.circulationA = circulationA; } } 复制代码
SpringContextConfig.xmlcirculationa 用给定的构造函数实例化; circulationb 就用默认的实例化方法(默认的空构造函数)
<bean id="circulationa" class="src.bean.CirculationA"> <constructor-arg name="circulationB" ref="circulationb"/> </bean> <bean id="circulationb" class="src.bean.CirculationB" > <property name="circulationA" ref="circulationa"/> </bean> 复制代码
好,例子准完毕,上面的例子是 circulationa的构造函数里面有circulationb;然后circulationb属性里面有circulationa; 启动容器!结果如下:
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'circulationa' defined in class path resource [config.xml]: Cannot resolve reference to bean 'circulationb' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'circulationb' defined in class path resource [config.xml]: Cannot resolve reference to bean 'circulationa' while setting bean property 'circulationA'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'circulationa': Requested bean is currently in creation: Is there an unresolvable circular reference? Exception in thread "main" org.springframework.beans.factory.BeanCreationException