【发布时间】:2016-10-06 20:21:06
【问题描述】:
考虑以下代码:
这是A类
public class A {
public A() {
System.out.println("Creating instance of A");
}
private B b;
public void setB(B b) {
System.out.println("Setting property b of A instance");
this.b = b;
}
}
这里是B类
public class B {
public B() {
System.out.println("Creating instance of B");
}
private A a;
public void setA(A a) {
System.out.println("Setting property a of B instance");
this.a = a;
}
}
我们有这个配置文件:
<bean id="a" class="mypackage.A">
<property name="b" ref="b" />
</bean>
<bean id="b" class="mypackage.B">
<property name="a" ref="a" />
</bean>
输出:
Creating instance of A
Creating instance of B
Setting property a of B instance
Setting property b of A instance
当a 注入b 时,a 尚未完全初始化。
我的问题:
尽管当 'b' 引用 'a' 时 'a' 没有完全初始化,但片刻之后 'a' 将完全初始化。由于“b”引用了“a”,那么“b”将在片刻后指向完全初始化的“a”。
通常给出这种解释是为了显示循环依赖的缺点。
但最终我们遇到了完全初始化的 bean 'a' 和 'b' 相互指向的正常情况。那么,这个例子如何向我们展示了使用循环依赖的缺点呢?
我会引用 spring 文档:
与典型情况(没有循环依赖)不同,循环 bean A 和 bean B 之间的依赖关系强制 bean 之一 在完全初始化之前注入另一个(一个 经典的鸡/蛋场景)
【问题讨论】:
-
问题是什么? Spring确实支持循环依赖
-
是的,但不建议使用它。他们给出的原因如上所示。我的反驳论点也如上所示。
-
现在尝试添加一个
@PostConstruct方法,其中A使用B和B使用A。其中一个会破裂。因为要么 A 在使用前没有完全初始化,要么 B 在使用时没有完全初始化。如果出于任何原因您有一个无副作用的二传手,它也可能会损坏。具有循环依赖会使您的代码变得脆弱,并可能导致运行时出现奇怪的行为(尤其是在启动/初始化代码中)。更不用说根据需要它甚至可能会使编译器感到困惑。
标签: spring