最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring三級緩存解決循環(huán)依賴的解析過程

 更新時間:2025年05月04日 21:02:44   作者:時光不負(fù)追夢人  
這篇文章主要介紹了Spring三級緩存解決循環(huán)依賴的解析過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

一、循環(huán)依賴場景

假設(shè)存在兩個Bean的相互依賴:

@Component
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
}

@Component
public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

二、三級緩存定義

DefaultSingletonBeanRegistry 中定義:

// 一級緩存:完整Bean(K:Bean名稱 V:實(shí)例化+初始化完成的Bean)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 二級緩存:早期暴露對象(K:Bean名稱 V:未完成屬性注入的原始Bean)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

// 三級緩存:對象工廠(K:Bean名稱 V:ObjectFactory)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

三、解決流程(以ServiceA和ServiceB為例)

1. 創(chuàng)建ServiceA

sequenceDiagram
    participant Container
    participant Cache1 as singletonObjects
    participant Cache2 as earlySingletonObjects
    participant Cache3 as singletonFactories
    
    Container->>Cache1: 檢查ServiceA是否存在
    Cache1-->>Container: 不存在
    Container->>Container: 實(shí)例化ServiceA(構(gòu)造器調(diào)用)
    Container->>Cache3: 添加ServiceA的ObjectFactory
    Container->>Container: 開始屬性注入(需要ServiceB)

關(guān)鍵代碼段

// AbstractAutowireCapableBeanFactory#doCreateBean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

2. 發(fā)現(xiàn)需要ServiceB

sequenceDiagram
    participant Container
    participant Cache1
    participant Cache2
    participant Cache3
    
    Container->>Cache1: 檢查ServiceB是否存在
    Cache1-->>Container: 不存在
    Container->>Container: 實(shí)例化ServiceB(構(gòu)造器調(diào)用)
    Container->>Cache3: 添加ServiceB的ObjectFactory
    Container->>Container: 開始屬性注入(需要ServiceA)

3. 解決ServiceB對ServiceA的依賴

sequenceDiagram
    participant Container
    participant Cache1
    participant Cache2
    participant Cache3
    
    Container->>Cache1: 查找ServiceA
    Cache1-->>Container: 不存在
    Container->>Cache2: 查找ServiceA
    Cache2-->>Container: 不存在
    Container->>Cache3: 獲取ServiceA的ObjectFactory
    Container->>Container: 執(zhí)行g(shù)etEarlyBeanReference()
    Container->>Cache2: 將生成的代理對象存入earlySingletonObjects
    Container->>ServiceB: 注入ServiceA的早期引用
    Container->>Container: 完成ServiceB初始化
    Container->>Cache1: 將ServiceB放入singletonObjects

4. 回溯完成ServiceA初始化

sequenceDiagram
    participant Container
    participant Cache1
    participant Cache2
    participant Cache3
    
    Container->>ServiceA: 注入已初始化的ServiceB
    Container->>Container: 執(zhí)行ServiceA的初始化后方法
    Container->>Cache1: 將ServiceA放入singletonObjects
    Container->>Cache2: 移除ServiceA的早期引用
    Container->>Cache3: 移除ServiceA的ObjectFactory

四、關(guān)鍵機(jī)制詳解

1. getEarlyBeanReference() 的核心作用

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    // 如果有必要,在此處生成代理對象
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = 
                    (SmartInstantiationAwareBeanPostProcessor) bp;
                bean = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return bean;
}

2. 三級緩存必要性分析

緩存級別解決的問題典型場景
singletonFactories處理AOP代理的延遲生成需要保證代理對象的單例性
earlySingletonObjects避免重復(fù)創(chuàng)建早期引用多個Bean依賴同一個未完成初始化的Bean
singletonObjects存儲最終可用Bean正常Bean獲取

五、設(shè)計約束與限制

1.僅支持單例作用域

原型(prototype)作用域的Bean無法解決循環(huán)依賴,因?yàn)镾pring不緩存原型Bean

2.構(gòu)造器注入限制

如果循環(huán)依賴通過構(gòu)造器注入發(fā)生,無法解決(實(shí)例化前就需要完成依賴注入)

3.異步初始化風(fēng)險

使用@Async等方法增強(qiáng)的Bean可能破壞初始化順序

六、調(diào)試技巧

查看緩存狀態(tài) 

DefaultSingletonBeanRegistry 類中設(shè)置斷點(diǎn):

// 查看三級緩存內(nèi)容
System.out.println("singletonFactories: " + singletonFactories.keySet());
System.out.println("earlySingletonObjects: " + earlySingletonObjects.keySet());
System.out.println("singletonObjects: " + singletonObjects.keySet());

強(qiáng)制拋出循環(huán)依賴異常

在配置類添加:

@Bean
public CircularReferencesBean circularReferencesBean() {
    return new CircularReferencesBean(circularReferencesBean());
}

七、性能優(yōu)化建議

避免過度使用循環(huán)依賴

即使技術(shù)可行,也應(yīng)通過設(shè)計模式(如事件驅(qū)動)解耦

合理使用@Lazy注解

延遲加載非必要依賴:

@Autowired
@Lazy
private ServiceB serviceB;

監(jiān)控緩存命中率

通過JMX監(jiān)控 singletonObjectsearlySingletonObjects 的比例

總結(jié)

Spring的三級緩存機(jī)制通過 提前暴露對象引用 + 動態(tài)代理生成 的協(xié)同設(shè)計,在保證單例性的前提下,優(yōu)雅地解決了循環(huán)依賴問題。理解該機(jī)制需要重點(diǎn)把握Bean生命周期的階段劃分和緩存狀態(tài)的轉(zhuǎn)換邏輯。

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java字符串與格式化輸出的深入分析

    java字符串與格式化輸出的深入分析

    本篇文章是對java字符串與格式化輸出進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 使用mybatis攔截器處理敏感字段

    使用mybatis攔截器處理敏感字段

    這篇文章主要介紹了mybatis攔截器處理敏感字段方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java實(shí)現(xiàn)的2048游戲完整實(shí)例

    java實(shí)現(xiàn)的2048游戲完整實(shí)例

    這篇文章主要介紹了java實(shí)現(xiàn)的2048游戲,結(jié)合完整實(shí)例形式分析了java實(shí)現(xiàn)2048游戲功能的相關(guān)數(shù)值運(yùn)算、swing組件布局、事件響應(yīng)等相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • java8新特性之方法引用示例代碼

    java8新特性之方法引用示例代碼

    這篇文章主要給大家介紹了關(guān)于java8新特性之方法引用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 使用Java實(shí)現(xiàn)對兩個秒級時間戳相加

    使用Java實(shí)現(xiàn)對兩個秒級時間戳相加

    在現(xiàn)代應(yīng)用程序開發(fā)中,時間戳的處理是一個常見需求,特別是當(dāng)我們需要對時間戳進(jìn)行運(yùn)算時,比如時間戳的相加操作,本文我們將探討如何使用Java對兩個秒級時間戳進(jìn)行相加,并展示詳細(xì)的代碼示例和運(yùn)行結(jié)果,需要的朋友可以參考下
    2024-08-08
  • Java與Android使用監(jiān)聽者模式示例

    Java與Android使用監(jiān)聽者模式示例

    這篇文章主要為大家介紹了Java與Android使用監(jiān)聽者模式示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 源碼解析Spring 數(shù)據(jù)庫異常抽理知識點(diǎn)總結(jié)

    源碼解析Spring 數(shù)據(jù)庫異常抽理知識點(diǎn)總結(jié)

    在本篇文章里小編給大家分享了關(guān)于源碼解析Spring 數(shù)據(jù)庫異常抽理知識點(diǎn)內(nèi)容,對此有需要的朋友們學(xué)習(xí)參考下。
    2019-05-05
  • Spring中Bean初始化和銷毀的方式總結(jié)

    Spring中Bean初始化和銷毀的方式總結(jié)

    這篇文章主要為大家整理了Spring中Bean初始化和銷毀的多種方式,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的可以了解一下
    2023-04-04
  • Mybatis基于注解形式的sql語句生成實(shí)例代碼

    Mybatis基于注解形式的sql語句生成實(shí)例代碼

    這篇文章主要介紹了 Mybatis基于注解形式的sql語句生成實(shí)例代碼,需要的朋友可以參考下
    2017-09-09
  • SSM項目中使用攔截器和過濾器的實(shí)現(xiàn)示例

    SSM項目中使用攔截器和過濾器的實(shí)現(xiàn)示例

    這篇文章主要介紹了SSM項目中使用攔截器和過濾器的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論

黄石市| 盐亭县| 峨眉山市| 广平县| 大方县| 沿河| 平潭县| 攀枝花市| 汪清县| 芜湖县| 治县。| 柳州市| 灵山县| 渝北区| 博白县| 新巴尔虎右旗| 土默特右旗| 西乡县| 张家界市| 冷水江市| 通榆县| 胶州市| 遂川县| 开封市| 罗江县| 四子王旗| 浙江省| 夏津县| 东海县| 丹寨县| 商河县| 康定县| 五常市| 孟津县| 三江| 三亚市| 永泰县| 京山县| 察雅县| 乐都县| 泉州市|