Spring bean建立之迴圈依賴與三級快取
Spring bean建立之迴圈依賴與三級快取
迴圈依賴
多個物件之間互相引用形成環
如果使用普通new方法建立,物件之間會迴圈建立導致OOM
三級快取
- 一級快取:singletonObjects
- 二級快取:earlySingletonObjects
- 三級快取:singletonFactories
在建立物件時會按照:一級--->二級--->三級的順序嘗試獲取物件
bean的建立
對於ClassPathXmlApplicationContext獲取bean物件,前置有一系列方法初始化容器、定義BeanFactoryPostProcess、國際化、多播器等的準備工作。
核心物件建立物件方法:
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
堆疊資訊:
之後將會迴圈遍歷需要建立bean物件的列表,呼叫getBean方法
嘗試從三級快取中獲取:
獲取不到,只能建立物件:
將會呼叫lambda表示式中的createBean進行物件的建立
到此物件已經例項化完成,需要進行初始化,不過在呼叫populateBeanff初始化前,將呼叫addSingletonFactory方法將包含自身例項的objectFactory放入第三級快取中。
具體的實現方法:
為了解決依賴的物件不存在的問題,同樣是依靠getBean方法解決
不過這一次,在第三級快取中可以獲取到迴圈依賴的物件(假設是兩個物件之間迴圈依賴,開始建立的是A物件,目前建立的是B物件,此時B物件可以從第三級快取中獲取到例項化的A物件,直接裝配到B物件中)
此時獲取到只例項化的A物件後,將第三級快取中的A物件移除,放到二級快取中,值得注意的是B物件在初始化前也會將自己放入三級快取中,由於自身的依賴已經解決,B物件在getSingleton方法返回前又會將自己的從三級快取中刪除放到一級快取中。
至此B物件已經初始化完成,只需將屬性注入到A中即可,而A物件被初始化完成之後也會將自己從二三級快取中刪除,放入到一級快取中,至此A物件建立完成。
在for迴圈遍歷下一個需要建立的Bean時,會直接從快取中獲取,不需要再例項化、初始化。
整個過程的堆疊資訊:
流程圖: