Spring循環依賴解決原理


循環依賴問題如果不解決, 會導致棧溢出異常, 循環圈內的實例無法創建

例如: 有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;
}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM