深度解析 Spring 源碼:三級緩存機制探究

Spring 框架中的三級緩存機制主要與 `AbstractAutowireCapableBeanFactory` 類中的 `doCreateBean` 方法在解析和創建單例 bean 時所使用的緩存有關。這個機制主要用於解決循環依賴的問題,尤其是在構造器註入的場景下。以下是對 Spring 三級緩存機制的深度解析:

1. 三級緩存的定義

深度解析 Spring 源碼:三級緩存機制探究

* 一級緩存(singletonObjects):存儲完全初始化好的 bean,即 bean 的所有屬性都已被設置,並且完成了初始化方法(如果有的話)的調用。

* 二級緩存(earlySingletonObjects):存儲提前暴露的 bean 實例的原始對象(即未完成屬性填充的對象)。這個緩存主要是為了解決循環依賴的問題。當一個 bean 的創建依賴於另一個尚未創建完成的 bean 時,這個尚未完成的 bean 會被提前暴露到這個二級緩存中,供其他 bean 使用。

* 三級緩存(singletonFactories):存儲 bean 的工廠對象(`ObjectFactory`),用於創建 bean 的實例。這個緩存主要用於解決 AOP 代理的問題。當 bean 需要被 AOP 代理時,Spring 會在這個緩存中保存一個能夠創建代理對象的工廠,而不是直接保存代理對象本身。

 2. 緩存的使用流程

1. 創建 bean:當一個 bean 需要被創建時,Spring 首先會檢查一級緩存(singletonObjects)中是否存在該 bean 的實例。如果存在,則直接返回;否則,進入下一步。

2. 檢查是否存在循環依賴:在創建 bean 的過程中,如果發現該 bean 依賴於另一個尚未創建完成的 bean(即存在循環依賴),那麼 Spring 會嘗試從二級緩存(earlySingletonObjects)中獲取該依賴 bean 的實例。如果找到了,則使用該實例;否則,繼續下一步。

3. 提前暴露 bean:如果發現了循環依賴,但是二級緩存中沒有該依賴 bean 的實例,那麼 Spring 會提前將該 bean 的實例(尚未完成屬性填充的對象)暴露到二級緩存中,供其他 bean 使用。

4. 創建代理對象(如果需要):如果 bean 需要被 AOP 代理,那麼 Spring 會在這個步驟中創建代理對象。但是,代理對象本身並不會直接保存到緩存中,而是會保存一個能夠創建代理對象的工廠(`ObjectFactory`)到三級緩存(singletonFactories)中。

5. 填充屬性:完成 bean 的屬性填充(即依賴註入)。

6. 初始化 bean:調用 bean 的初始化方法(如果有的話)。

7. 完成創建並保存:將完全初始化好的 bean 保存到一級緩存(singletonObjects)中,並從二級緩存(earlySingletonObjects)和三級緩存(singletonFactories)中移除該 bean 的相關條目。

3. 為什麼要使用三級緩存

* 解決循環依賴:二級緩存的存在主要是為了解決循環依賴的問題。通過提前暴露 bean 的實例,可以確保在依賴註入時能夠找到所需的依賴對象。

* 支持 AOP:三級緩存的存在主要是為了支持 AOP。當 bean 需要被 AOP 代理時,Spring 不會直接保存代理對象到緩存中,而是保存一個能夠創建代理對象的工廠。這樣做的好處是,只有當真正需要代理對象時,才會去創建它,從而避免了不必要的性能開銷。

總結

Spring 的三級緩存機制是一個非常重要的特性,它使得 Spring 能夠在保證單例性的同時,支持循環依賴和 AOP。通過合理地使用這三個緩存,Spring 能夠高效地創建和管理 bean,從而確保整個應用程序的穩定性和性能。

分享給朋友:

“深度解析 Spring 源碼:三級緩存機制探究” 的相關文章

一個簡單的 HTML5 導航菜單的示例代碼

一個簡單的 HTML5 導航菜單的示例代碼

以下是一個簡單的 HTML5 導航菜單的示例代碼,這個導航菜單使用了 HTML5 中的 `nav` 標簽來包裝整個菜單,使用了 Flex 布局來對菜單進行布局和對齊,同時也設置了一些簡單的樣式來美化菜單。…

JS跳轉頁面代碼及例子

JS跳轉頁面代碼及例子

JS跳轉頁面是一種很常見的前端交互技術,下面是幾種跳轉頁面的方式:1. 直接修改 `window.location.href` 屬性,2. 使用 `window.location.replace` 方法,此方法會替換當前頁面歷史記錄,不會在瀏覽器歷史記錄中留下痕跡。3. 使用 `window.ope…

一個簡單的html放煙花特效的代碼

一個簡單的html放煙花特效的代碼

以下是一個簡單的html放煙花特效的代碼,代碼說明:1. 使用html和css定義了一個煙花的基本樣式;2. 使用javascript動態生成多個煙花元素,並使用animation讓其展開,模擬煙花爆炸效果;3. 使用setTimeout函數控制煙花爆炸持續時間,並使用setInterval控制煙花…

星空特效的HTML代碼示例

星空特效的HTML代碼示例

以下是一個星空特效的HTML代碼示例:這個代碼會在頁面背景中生成100個閃爍的星星,使得整個頁面看起來像是夜空中的星空。可以在瀏覽器中運行查看效果。這些代碼可以在瀏覽器中運行並產生相應的星空特效。…

用html和CSS3制作酷炫的導航欄代碼及例子

用html和CSS3制作酷炫的導航欄代碼及例子

使用HTML5和CSS3的新特性可以制作出很多酷炫的導航欄效果,例如下拉菜單、響應式導航欄、帶有動態效果的導航欄等等。下面以下拉菜單為例,具體步驟如下:1. 創建 HTML 結構;2. 設置基本樣式;3. 添加動態效果。這樣就可以制作出下拉菜單效果,當滑鼠懸停在菜單項上時,菜單項下面的下拉菜單顯示出…

html5的doctype,通過DOCTYPE聲明

html5的doctype,通過DOCTYPE聲明

HTML5中的DOCTYPE聲明為 `<!DOCTYPE html>`,格式簡單清晰。相較於之前的文檔類型聲明格式,它更加簡單,也更具可讀性。同時,在HTML5中取消了文檔類型規範中過時的部分,這使得DOCTYPE的作用也更加直接和明確。通過DOCTYPE聲明,瀏覽器、解釋器才能正確地解…