Spring 源码阅读-循环依赖
2016-08-15 00:00
671 查看
#Spring 源码阅读-循环依赖
##一. 循环依赖
Spring中产生循环依赖有三种情况
1.构造器循环依赖
代码示例
错误信息
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?
分析
Spring容器将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
1、Spring容器创建“modelA” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelB”,并将“modelA” 标识符放到“当前创建Bean池”;
2、Spring容器创建“modelB” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelC”,并将“modelB” 标识符放到“当前创建Bean池”;
3、Spring容器创建“modelC” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelA”,并将“modelC” 标识符放到“当前创建Bean池”;
4、到此为止Spring容器要去创建“modelA”Bean,发现该Bean 标识符在“当前创建Bean池”中,因为表示循环依赖,抛出BeanCurrentlyInCreationException。
2.Setter循环依赖
分析
1、Spring容器创建单例“modelA”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的Bean,并将“modelA”标识符放到“当前创建Bean池”;然后进行setter注入“modelB”;
2、Spring容器创建单例“modelB”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的Bean,并将“modelB” 标识符放到“当前创建Bean池”,然后进行setter注入“modelC”;
3、Spring容器创建单例“modelC”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory ”用于返回一个提前暴露一个创建中的Bean,并将“modelC” 标识符放到“当前创建Bean池”,然后进行setter注入“modelA”;进行注入“modelA”时由于提前暴露了“ObjectFactory”工厂从而使用它返回提前暴露一个创建中的Bean;
4、最后再依赖注入“modelB”和“modelA”,完成setter注入。
3.prototype循环依赖
错误信息
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。
##一. 循环依赖
Spring中产生循环依赖有三种情况
1.构造器循环依赖
代码示例
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?
分析
Spring容器将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
1、Spring容器创建“modelA” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelB”,并将“modelA” 标识符放到“当前创建Bean池”;
2、Spring容器创建“modelB” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelC”,并将“modelB” 标识符放到“当前创建Bean池”;
3、Spring容器创建“modelC” Bean,首先去“当前创建Bean池”查找是否当前Bean正在创建,如果没发现,则继续准备其需要的构造器参数“modelA”,并将“modelC” 标识符放到“当前创建Bean池”;
4、到此为止Spring容器要去创建“modelA”Bean,发现该Bean 标识符在“当前创建Bean池”中,因为表示循环依赖,抛出BeanCurrentlyInCreationException。
2.Setter循环依赖
分析
1、Spring容器创建单例“modelA”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的Bean,并将“modelA”标识符放到“当前创建Bean池”;然后进行setter注入“modelB”;
2、Spring容器创建单例“modelB”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory”用于返回一个提前暴露一个创建中的Bean,并将“modelB” 标识符放到“当前创建Bean池”,然后进行setter注入“modelC”;
3、Spring容器创建单例“modelC”Bean,首先根据无参构造器创建Bean,并暴露一个“ObjectFactory ”用于返回一个提前暴露一个创建中的Bean,并将“modelC” 标识符放到“当前创建Bean池”,然后进行setter注入“modelA”;进行注入“modelA”时由于提前暴露了“ObjectFactory”工厂从而使用它返回提前暴露一个创建中的Bean;
4、最后再依赖注入“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。
相关文章推荐
- Spring源码阅读-BeanFactory-循环依赖
- spring 源码探索--单例bean解决循环依赖问题
- Spring源码解析:循环依赖的探测与处理
- Spring源码-IOC容器(六)-bean的循环依赖
- Spring源码阅读 之依赖注入的实现方式
- Spring源码阅读(三)—IOC容器依赖注入
- Spring源码学习--Bean对象循环依赖问题解决(四)
- Spring源码解析笔记5——循环依赖的解决
- spring 源码-循环依赖
- Spring源码(六)-Spring循环依赖的解决方案
- 从spring源码角度分析循环依赖bean的组装
- spring源码分析 循环依赖
- Spring源码解析 ---- 循环依赖
- Spring 源码阅读(二)——Spring的初始化以及资源加载
- 【Spring学习笔记】之【3.2 避免循环依赖】
- 初始化IoC容器(Spring源码阅读)-我们到底能走多远系列(31)
- Spring 源码阅读(1)
- Spring源码阅读1---导入eclipse
- spring-mvc源码阅读(二)<mvc:annotation-driven/>做了什么
- Argo源码阅读(三):Google-guice依赖注入框架