spring 源码-循环依赖
2017-05-11 23:57
483 查看
可能有点标题党,现在并不涉及循环依赖的源码,准备之后写。
在现实的需求中,或许我们会碰到这种需求,我中有你,你中有我。
这特么设么需求,用类A、B来表示,就是类A中有个属性B,类B中有个属性A。
那么如果把A、B放入到spring容器之中呢。。。
之前碰到一次有人写了这种循环依赖的代码,但是怎么说从可读性上、理解性上都不是很好,我看了之后,抽取了一些方法逻辑,写成了三个类。因为在之前去掉了一些不必要的autowired属性,然后程序就挂了。这是为什么。如下,类B中有如下方法,
@PostConstruct
public void printAProperty() {
System.out.println(“B的asd属性—————-” + this.asd + “—————-“);
System.out.println(“A的asd属性—————-” + a.getAsd() + “—————-“);
}
这是为什么呢
因为在A初始化的时候,发现B没有初始化,然后开始创建Bean B,现在B发现依赖于A,并且A是单例的并且在创建之中,那么会先提前暴露A,此时在B中的A的值,的asd属性为null,又由于是postconstruct注解标注的方法,此时还在B调用完构造方法后执行后置处理的过程内,所以会输出如下情况的
B的asd属性—————-aasdasd—————-
A的asd属性—————-null—————-
如果此时使用A的属性进行,一些连接池的初始化等等。。。记得当时的代码就是初始化某个连接池、、、那么应用是获取不到配置信息的。
在spring中,循环依赖的解决方式是通过无参构造函数提前暴露bean实例,当然这样只能解决单例的循环依赖,因为原型模式的话,应用是不缓存bean实例的,所以每一次的bean都不是同一个,循环依赖是无法解决的。因为之前提前暴露的都是放在单例Factory缓存中的。当然如果有原型factory缓存的话,那么bean就不是原型模式的了。由以上也可以推断出来,spring 不支持构造器里面的循环依赖 的,因为在构造器循环依赖中,比如创建A的实例,那么需要创建B的实例,但是又需要A的实例,变成一个死锁。无法解决。
总结两点
1.spring 通过提前根据无参构造函数暴露实例。必须要保证在有有参构造函数的时候,手动添加一个无参构造函数
2.spring 不支持原型模式和构造器的循环依赖
tip:
context.setAllowCircularReferences(false);禁用循环依赖
context.setAllowBeanDefinitionOverriding(false);禁用同名bean覆盖
在现实的需求中,或许我们会碰到这种需求,我中有你,你中有我。
这特么设么需求,用类A、B来表示,就是类A中有个属性B,类B中有个属性A。
那么如果把A、B放入到spring容器之中呢。。。
之前碰到一次有人写了这种循环依赖的代码,但是怎么说从可读性上、理解性上都不是很好,我看了之后,抽取了一些方法逻辑,写成了三个类。因为在之前去掉了一些不必要的autowired属性,然后程序就挂了。这是为什么。如下,类B中有如下方法,
@PostConstruct
public void printAProperty() {
System.out.println(“B的asd属性—————-” + this.asd + “—————-“);
System.out.println(“A的asd属性—————-” + a.getAsd() + “—————-“);
}
这是为什么呢
因为在A初始化的时候,发现B没有初始化,然后开始创建Bean B,现在B发现依赖于A,并且A是单例的并且在创建之中,那么会先提前暴露A,此时在B中的A的值,的asd属性为null,又由于是postconstruct注解标注的方法,此时还在B调用完构造方法后执行后置处理的过程内,所以会输出如下情况的
B的asd属性—————-aasdasd—————-
A的asd属性—————-null—————-
如果此时使用A的属性进行,一些连接池的初始化等等。。。记得当时的代码就是初始化某个连接池、、、那么应用是获取不到配置信息的。
在spring中,循环依赖的解决方式是通过无参构造函数提前暴露bean实例,当然这样只能解决单例的循环依赖,因为原型模式的话,应用是不缓存bean实例的,所以每一次的bean都不是同一个,循环依赖是无法解决的。因为之前提前暴露的都是放在单例Factory缓存中的。当然如果有原型factory缓存的话,那么bean就不是原型模式的了。由以上也可以推断出来,spring 不支持构造器里面的循环依赖 的,因为在构造器循环依赖中,比如创建A的实例,那么需要创建B的实例,但是又需要A的实例,变成一个死锁。无法解决。
总结两点
1.spring 通过提前根据无参构造函数暴露实例。必须要保证在有有参构造函数的时候,手动添加一个无参构造函数
2.spring 不支持原型模式和构造器的循环依赖
tip:
context.setAllowCircularReferences(false);禁用循环依赖
context.setAllowBeanDefinitionOverriding(false);禁用同名bean覆盖
相关文章推荐
- Spring源码阅读-BeanFactory-循环依赖
- spring源码分析 循环依赖
- Spring源码-IOC容器(六)-bean的循环依赖
- Spring源码解析:循环依赖的探测与处理
- 从spring源码角度分析循环依赖bean的组装
- Spring源码(六)-Spring循环依赖的解决方案
- Spring源码解析笔记5——循环依赖的解决
- spring 源码探索--单例bean解决循环依赖问题
- Spring源码解析 ---- 循环依赖
- Spring源码学习--Bean对象循环依赖问题解决(四)
- Spring 源码阅读-循环依赖
- Spring源码解析:Bean的实例化与依赖注入(四)
- Spring之循环依赖
- Spring源码解析 依赖注入
- 【第三章】 DI 之 3.2 循环依赖 ——跟我学spring3
- 【第三章】 DI 之 3.2 循环依赖 ——跟我学spring3
- spring依赖注入源码分析和mongodb自带连接本地mongodb服务逻辑分析
- 菜鸟看spring源码(0)之BeanFactory的注册与依赖绑定
- Spring3学习笔记之(spring core之DI循环依赖)
- Spring如何解决循环依赖