深度解析 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 源碼:三級緩存機制探究” 的相關文章

mark元素使用紅色代表及例子

mark元素使用紅色代表及例子

在HTML中,<mark> 元素可以用於標記或強調文本中的重要或關鍵內容。這個元素通常會用醒目的紅色來渲染,因為紅色是一個視覺上非常具有註意力的顏色。在這種情況下,你可以將這些關鍵字用 <mark> 標簽包圍起來,使其突出顯示。這樣可以幫助用戶更快速地發現這個型號是這個品牌的旗艦機型,帶來更好的用戶體驗。需要註意的是,過度使用 <mark> 標簽會導致頁面顯得雜亂無章,影響閱讀體驗,因此應謹慎使用,只將最為關鍵的信息進行標記,達到凸顯重點的效果即可。…

mark點怎麼設置及設置例子

mark點怎麼設置及設置例子

mark 元素用於標記或高亮文本,非常適合用於文本搜索和結果導航。要在文本中使用 mark 元素,只需要將需要高亮的文本放在 mark 元素內即可。通常情況下,瀏覽器默認為高亮文本設置為黃色。 .highlight {    background-color: lightblue;    color: white;  }```上述代碼會將 mark 元素的背景顏色設置為淺藍色,文本顏色設置為白色。根據實際需要,您可以將顏色更改為您想要的顏色。…

一個簡單的html大海日出特效的代碼

一個簡單的html大海日出特效的代碼

以下是一個簡單的html大海日出特效的代碼:1. 使用html和css定義了一個大海和太陽的基本樣式;2. 使用animation讓太陽從初始位置向上升起,並且設置好其動畫屬性;3. 設置大海背景漸變和水面的動畫效果。…

html零基礎入門教程及代碼演示例子

html零基礎入門教程及代碼演示例子

HTML是創建網頁的基礎語言。在互聯網的世界裏,網頁是我們獲取信息和與世界連接的主要途徑之一。因此,學習HTML是設計和制作網頁的重要一步。如果您是一個完全零基礎的人,那麼這份教程可以幫助您快速入門,並開始創建自己的網頁。在這個教程中,我們將探討HTML的基礎語法和標記,以及如何將它們組合在一起來構建一個簡單的網頁。無需任何預備知識,您只需要在計算機上安裝一個文本編輯器和瀏覽器,就可以開始學習HTML。讓我們開始!…

html5的doctype,通過DOCTYPE聲明

html5的doctype,通過DOCTYPE聲明

HTML5中的DOCTYPE聲明為 `<!DOCTYPE html>`,格式簡單清晰。相較於之前的文檔類型聲明格式,它更加簡單,也更具可讀性。同時,在HTML5中取消了文檔類型規範中過時的部分,這使得DOCTYPE的作用也更加直接和明確。通過DOCTYPE聲明,瀏覽器、解釋器才能正確地解析HTML文檔,它是HTML文檔的必要組成部分。當聲明HTML5時,需要在HTML頁面的頂部開始HTML標記之前,添加 `<!DOCTYPE html>`。這樣瀏覽器就能識別頁面是由HTML5來定義的了。…

在Java編程語言中,類的三種訪問權限的區別

在Java編程語言中,類的三種訪問權限的區別

在Java編程語言中,類可以用public、protected或private關鍵字來指定訪問權限。這三種訪問權限有如下區別:1. public訪問權限:使用public關鍵字表示該類的成員可以被任何其他類訪問。2. protected訪問權限:使用protected關鍵字表示該類的成員可以被該類的子類和同一包中的其他類訪問。3. private訪問權限:使用private關鍵字表示該類的成員只能被該類的成員訪問。…