循环依赖问题如果不解决, 会导致栈溢出异常, 循环圈内的实例无法创建
例如: 有3个类: A, B, C. 其中A依赖B, B依赖C, C依赖A.
public class A {
private B b;
public B getB () {
return b;
}
public void setB (B b) {
this.b = b;
}
}
public class B {
private C c;
public C getC () {
return c;
}
public void setC (C c) {
this.c = c;
}
}
public class C {
private A a;
public A getA () {
return a;
}
public void setA (A a) {
this.a = a;
}
}
Util类定义了获取它们各自实例的getBean方法, 包含两步: 1. 获取被依赖的类的实例 2. 注入到当前实例
public class Util {
public static A getBeanA(){
A a = new A();
B b = getBeanB();
a.setB(b);
return a;
}
private static B getBeanB () {
B b = new B();
C c = getBeanC();
b.setC(c);
return b;
}
private static C getBeanC () {
C c = new C();
A a = getBeanA();
c.setA(a);
return c;
}
}
public class App {
public static void main (String[] args) {
A beanA = Util.getBeanA();
}
}
当调用getBeanA时,就引发栈溢出异常,其根因是: 实例A时,发现需要实例B, 而实例B时发现需要实例C, 而实例C时又发现需要先实例A,可是A的实例还在等待B实例的完成, 彼此间像死锁一样缠住了.
解决方法: 提前暴露半成品的实例 : 在被需要时, 直接将这个半成品给需要者.
public class Util {
// 缓存半成品的实例
public static Map<String, Object> earlyBeanMap = new HashMap<String, Object>(3);
public static A getBeanA(){
// 先从半成品中拿依赖的实例, 如果没有才新建
if(earlyBeanMap.containsKey("a")){
return (A)earlyBeanMap.get("a");
}
A a = new A();
earlyBeanMap.put("a",a);
B b = getBeanB();
a.setB(b);
return a;
}
private static B getBeanB () {
if(earlyBeanMap.containsKey("b")){
return (B)beanMap.get("b");
}
B b = new B();
earlyBeanMap.put("b",b);
C c = getBeanC();
b.setC(c);
return b;
}
private static C getBeanC () {
if(earlyBeanMap.containsKey("c")){
return (C)earlyBeanMap.get("c");
}
C c = new C();
earlyBeanMap.put("c",c);
A a = getBeanA();
c.setA(a);
return c;
}
}