目錄
一. 循環依賴的本質矛盾
1. 什么是循環依賴?
2. 矛盾的核心
二.? 三級緩存架構解析
三級緩存工作流程圖?編輯
三、為什么必須三級緩存?
1. 二級緩存的致命缺陷
2. 三級緩存的精妙設計
四、場景推演:三級緩存如何解決代理問題
1. 正常流程(無循環依賴)
2. 循環依賴流程??編輯
五、源碼級驗證
1. 三級緩存獲取邏輯
?2. 代理對象生成點
六、如果強行使用二級緩存
在 Spring 框架中,循環依賴(Circular Dependency)是開發過程中最常見的陷阱之一。Spring 通過三級緩存機制優雅地解決了這一問題,但許多開發者會疑惑:為什么需要三級緩存?二級緩存能否實現同樣的效果?本文將通過源碼分析、場景推演和設計哲學,揭示這一機制背后的精妙設計。
一. 循環依賴的本質矛盾
1. 什么是循環依賴?
當兩個或多個 Bean 相互依賴時,就會形成循環依賴:
// Bean A 依賴 Bean B
@Component
public class A {@Autowiredprivate B b;
}// Bean B 依賴 Bean A
@Component
public class B {@Autowiredprivate A a;
}
2. 矛盾的核心
-
構造器注入無法解決循環依賴:必須通過 Setter 或字段注入。
-
Bean 創建的生命周期沖突:
二.? 三級緩存架構解析
Spring 通過三級緩存解決循環依賴問題,其核心數據結構如下:
緩存級別 | 數據結構 | 存儲內容 |
---|---|---|
一級緩存 | singletonObjects | 完全初始化完成的單例 Bean |
二級緩存 | earlySingletonObjects | 提前暴露的早期 Bean(未完成屬性注入) |
三級緩存 | singletonFactories | Bean 的 ObjectFactory(用于生成代理對象) |
三級緩存工作流程圖
三、為什么必須三級緩存?
1. 二級緩存的致命缺陷
假設只有一級緩存 + 二級緩存:
-
場景:Bean A 依賴 Bean B,Bean B 依賴 Bean A,且 A 需要 AOP 代理
-
問題鏈:
-
A 實例化后放入二級緩存(原始對象)
-
B 從二級緩存獲取 A 的原始對象并注入
-
A 完成初始化后需要生成代理對象
-
結果:B 中持有的是 A 的原始對象,與最終代理對象不一致
-
2. 三級緩存的精妙設計
通過?ObjectFactory
?延遲處理代理:
// AbstractAutowireCapableBeanFactory
protected Object getEarlyBeanReference(String beanName, Object bean) {// 通過后置處理器生成代理對象return applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
-
動態決策:只有在發生循環依賴時才會調用 ObjectFactory
-
代理一致性:保證所有依賴方拿到的是同一個代理對象
四、場景推演:三級緩存如何解決代理問題
1. 正常流程(無循環依賴)
2. 循環依賴流程?
五、源碼級驗證
1. 三級緩存獲取邏輯
// DefaultSingletonBeanRegistry
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;
}
?2. 代理對象生成點
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(...) {// 1. 實例化對象instanceWrapper = createBeanInstance(beanName, mbd, args);// 2. 加入三級緩存addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// 3. 屬性填充(可能觸發循環依賴)populateBean(beanName, mbd, instanceWrapper);// 4. 初始化(生成最終代理對象)exposedObject = initializeBean(beanName, exposedObject, mbd);
}
六、如果強行使用二級緩存?
假設合并三級緩存中的?singletonFactories
?和?earlySingletonObjects
,會導致:
-
提前暴露未完成對象:可能將半成品 Bean 暴露給其他線程
-
代理對象不一致:普通 Bean 與代理 Bean 可能同時存在
-
內存泄漏風險:無法及時清理創建失敗的 Bean 引用