Springboot Bean循環依賴問題


參考博客原文地址:
https://www.jb51.net/article/168398.htm
https://www.cnblogs.com/mianteno/p/10692633.html
http://www.pianshen.com/article/4112200143/


1.構造器依賴循環

代碼示例:

@Component
public class A {
    private B b;
    @Autowired
    public A(B b) {
        this.b=b;
    }
}
@Component
public class B {
    private C c;
    @Autowired
    public B(C c) {
        this.c = c;
    }
}
@Component
public class C {
    private A a;
    @Autowired
    public C(A a) {
        this.a=a;
    }
}

啟動運行后運行結果:

可以看到異常的信息:

//org.springframework.beans.factory.BeanCurrentlyInCreationException
public BeanCurrentlyInCreationException(String beanName) {
		super(beanName,
				"Requested bean is currently in creation: Is there an unresolvable circular reference?");
	}

這種循環依賴沒有什么解決辦法,因為JVM虛擬機在對類進行實例化的時候,需先實例化構造器的參數,而由於循環引用這個參數無法提前實例化,故只能拋出錯誤。


2.屬性注入依賴循環

代碼示例:

@Component
public class A {
    @Autowired
    private B b;
    public A() {
        System.err.println(b);
    }
}
@Component
public class B {
    @Autowired
    private C c;
    public B() {
        System.err.println(c);
    }
}
@Component
public class C {
    @Autowired
    private A a;
    public C() {
        System.err.println(a);
    }
}

啟動運行后運行結果:

//程序正常啟動,輸出如下
null
null
null

結論:
Spring通過將實例化后的對象提前暴露給Spring容器中的singletonFactories,解決了循環依賴的問題


3.源碼分析 構造器循環依賴異常步驟及原因:

創建一個Bean的過程是:實例化->初始化(屬性)->放到緩存中,如下圖

這張圖是核心

getSingleton源碼:

//首次創建的beanName放入singletonsCurrentlyInCreation中
protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

構造器循環依賴,在初始化C時,需要先實例化A,但是A已經在singletonsCurrentlyInCreation有預實例化的記錄了,所以此處拋出異常。

public BeanCurrentlyInCreationException(String beanName) {
		super(beanName,
				"Requested bean is currently in creation: Is there an unresolvable circular reference?");
	}

源碼分析 Spring如何解決屬性注入 依賴循環問題:

//相關類
org.springframework.beans.factory.support.DefaultListableBeanFactory
org.springframework.beans.factory.support.AbstractBeanFactory
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

可以看到,在實例化后,Bean被添加到singletonFactories中了,所以可以獲取到Bean實例,解決了屬性循環依賴問題

try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}

4.最終總結:

構造器循環依賴:沒有什么解決辦法,因為JVM虛擬機在對類進行實例化的時候,需先實例化構造器的參數,而由於循環引用這個參數無法提前實例化,故只能拋出錯誤。
屬性循環依賴:Spring通過將實例化后的對象提前暴露給Spring容器中的singletonFactories,解決了循環依賴的問題


免責聲明!

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



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