Spring 源码阅读-循环依赖

#Spring 源码阅读-循环依赖spring

##一. 循环依赖spring-mvc

Spring中产生循环依赖有三种状况缓存

1.构造器循环依赖mvc

代码示例this

public class ModelA {
private ModelB modelB;
public ModelA(ModelB modelB){
    this.modelB=modelB;
}
public ModelB getModelB() {
    return modelB;
}
public void setModelB(ModelB modelB) {
    this.modelB = modelB;
}
}
	
	public class ModelB {
private ModelC modelC;
public ModelB(ModelC modelc){
    this.modelC=modelc;
}
public ModelC getModelC() {
    return modelC;
}
public void setModelC(ModelC modelC) {
    this.modelC = modelC;
}
}

public class ModelC {
private ModelA modelA;
public ModelA getModelA() {
    return modelA;
}
public void setModelA(ModelA modelA) {
    this.modelA = modelA;
}
public ModelC(ModelA modelA){
    this.modelA=modelA;
}
}

//配置文件

<bean id="modela" class="com.wm.ModelA">
    <constructor-arg index="0" ref="modelb"/>
</bean>
<bean id="modelb" class="com.wm.ModelB">
    <constructor-arg index="0" ref="modelc"/>
</bean>
<bean id="modelc" class="com.wm.ModelC">
    <constructor-arg index="0" ref="modela"/>
</bean>

//Client

ApplicationContext context=new ClassPathXmlApplicationContext ("/spring/spring-mvc.xml");
ModelC modelC=(ModelC)context.getBean("modelc");

错误信息 Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'modela': Requested bean is currently in creation: Is there an unresolvable circular reference?prototype

分析code

Spring容器将每个正在建立的Bean 标识符放在一个“当前建立Bean池”中,Bean标识符在建立过程当中将一直保持在这个池中,所以若是在建立Bean过程当中发现本身已经在“当前建立Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于建立完毕的Bean将从“当前建立Bean池”中清除掉。xml

一、Spring容器建立“modelA” Bean,首先去“当前建立Bean池”查找是否当前Bean正在建立,若是没发现,则继续准备其须要的构造器参数“modelB”,并将“modelA” 标识符放到“当前建立Bean池”;ci

二、Spring容器建立“modelB” Bean,首先去“当前建立Bean池”查找是否当前Bean正在建立,若是没发现,则继续准备其须要的构造器参数“modelC”,并将“modelB” 标识符放到“当前建立Bean池”;作用域

三、Spring容器建立“modelC” Bean,首先去“当前建立Bean池”查找是否当前Bean正在建立,若是没发现,则继续准备其须要的构造器参数“modelA”,并将“modelC” 标识符放到“当前建立Bean池”;

四、到此为止Spring容器要去建立“modelA”Bean,发现该Bean 标识符在“当前建立Bean池”中,由于表示循环依赖,抛出BeanCurrentlyInCreationException。

2.Setter循环依赖

分析 一、Spring容器建立单例“modelA”Bean,首先根据无参构造器建立Bean,并暴露一个“ObjectFactory”用于返回一个提早暴露一个建立中的Bean,并将“modelA”标识符放到“当前建立Bean池”;而后进行setter注入“modelB”;

二、Spring容器建立单例“modelB”Bean,首先根据无参构造器建立Bean,并暴露一个“ObjectFactory”用于返回一个提早暴露一个建立中的Bean,并将“modelB” 标识符放到“当前建立Bean池”,而后进行setter注入“modelC”;

三、Spring容器建立单例“modelC”Bean,首先根据无参构造器建立Bean,并暴露一个“ObjectFactory ”用于返回一个提早暴露一个建立中的Bean,并将“modelC” 标识符放到“当前建立Bean池”,而后进行setter注入“modelA”;进行注入“modelA”时因为提早暴露了“ObjectFactory”工厂从而使用它返回提早暴露一个建立中的Bean;

四、最后再依赖注入“modelB”和“modelA”,完成setter注入。

3.prototype循环依赖

//配置文件
	
 <bean id="modela" class="com.wm.ModelA" scope="prototype">
    <property name="modelB" ref="modelb" />
</bean>
<bean id="modelb" class="com.wm.ModelB" scope="prototype">
    <property name="modelC" ref="modelc"/>
</bean>
<bean id="modelc" class="com.wm.ModelC" scope="prototype">
    <property name="modelA" ref="modela"/>
</bean>

错误信息 Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'modela': Requested bean is currently in creation: Is there an unresolvable circular reference?

缘由

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

相关文章
相关标签/搜索