动态

详情 返回 返回

spring為什麼使用三級緩存而不是兩級? - 动态 详情

今天來聊一聊關於 Spring 為什麼使用三級緩存的問題,先説結果哈,Spring框架中的三級緩存主要用於解決循環依賴問題,特別是在單例Bean的創建過程中。

下面V哥會解釋為什麼Spring需要三級緩存,而不是僅僅使用兩級的原因。

  1. 一級緩存(Singleton Objects):存儲已經完全初始化好的單例Bean。當一個Bean被成功創建並注入到其他Bean中後,它會被放入一級緩存中。
  2. 二級緩存(Early Singleton Objects):存儲已經完成了BeanNameAware、BeanFactoryAware等Aware接口的回調,但是還沒有完全初始化的Bean。這個緩存主要用於存放早期引用的Bean,這些Bean在完成屬性填充和初始化方法調用之前,就可以被其他Bean引用。
  3. 三級緩存(Singleton Factories):存儲Bean工廠對象(BeanFactory)創建Bean實例的工廠信息。這個緩存是為了解決構造器循環依賴問題。當Spring容器創建一個Bean時,如果這個Bean的構造器依賴於其他Bean,Spring會首先嚐試創建這個Bean的實例,這個實例的引用會被放入三級緩存中。然後,Spring會嘗試創建依賴的Bean,如果依賴的Bean也存在循環依賴,Spring會從三級緩存中獲取Bean的早期引用,而不是再次創建一個新的實例。

為什麼需要三級緩存:

  • 解決循環依賴:在Spring中,如果兩個或多個Bean相互依賴對方的構造器,就會發生循環依賴。兩級緩存無法解決這個問題,因為它們都是在Bean實例化之後才被使用。三級緩存允許在Bean實例化過程中就提供對其他Bean的引用,從而打破循環依賴。
  • 優化性能:通過使用三級緩存,Spring可以在Bean實例化階段就解決循環依賴問題,避免了額外的Bean創建嘗試,從而提高了性能。
  • 保持Bean的創建過程的原子性:三級緩存確保了Bean的創建過程是原子性的,即在Bean完全初始化之前,不會將其暴露給其他Bean。
  • 支持延遲初始化:三級緩存允許Spring在Bean完全初始化之前,就能夠提供Bean的引用,這支持了延遲初始化的模式,即只有在Bean被實際使用時才進行初始化。

總而言之,言而總之,強調一下這句話:三級緩存是Spring框架解決循環依賴問題的關鍵機制,它允許在Bean的創建過程中提供對其他Bean的引用,同時保持了Bean創建的原子性和性能。

三級緩存使用案例

下面V 哥來一個簡單的使用案例,展示如何通過Spring的三級緩存機制解決循環依賴,方便兄弟們更好的理解。

首先,定義兩個Bean,它們在構造器中相互依賴:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ClassA {
    private ClassB classB;

    @Autowired
    public ClassA(ClassB classB) {
        this.classB = classB;
    }

    // ClassA的其他方法...
}

@Component
public class ClassB {
    private ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    // ClassB的其他方法...
}

在這個例子中,ClassAClassB通過構造器相互注入,形成了循環依賴。如果沒有Spring的三級緩存機制,這種情況會導致異常,因為Spring無法完成其中一個Bean的創建。

Spring框架內部是如何處理這個問題的呢?下面來介紹一下Spring容器創建這兩個Bean時的大致步驟,深入理解一下:

  1. Spring容器開始創建ClassA的Bean實例,並將其放入三級緩存singletonFactories中。
  2. 容器嘗試注入ClassBClassA的構造器中。由於ClassB還沒有完全創建,Spring會嘗試創建ClassB
  3. 在創建ClassB時,容器發現ClassB的構造器需要一個ClassA的實例。由於ClassA已經在三級緩存中,Spring會使用這個早期引用來注入ClassB
  4. 一旦ClassB被創建,它會被放入二級緩存earlySingletonObjects中,並完成剩餘的初始化步驟。
  5. 然後,容器繼續完成ClassA的創建和初始化,將其放入一級緩存singletonObjects中。

這樣的話,即使存在循環依賴,Spring也能夠通過三級緩存機制確保每個Bean都能被正確創建和注入,原來如此。

兄弟們可以移步 Spring 源碼,結合這個示例再深入學習,實際的Spring實現會更復雜一些。其實,咱們在使用Spring的的時候,通常不需要直接操作這些緩存,因為Spring容器會自動處理這些邏輯。到這,你應該知道Spring如何解決循環依賴的問題了,完事,下課。

user avatar god23bin 头像 wuyagege 头像 invalidnull 头像 wangzhongyang_go 头像 fenanjiu 头像 shawnphang 头像 shixiansheng_67ea5ae9c45b7 头像 wupeng_5a4de5c290b9d 头像 pxzsl 头像
点赞 9 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.