spring 源码-循环依赖

可能有点标题党,现在并不涉及循环依赖的源码,准备之后写。
在现实的需求中,或许我们会碰到这种需求,我中有你,你中有我。
这特么设么需求,用类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,framework,spring,循环依赖,源码,class)