首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Bean 載入全流程深度解析:從緩存暴露到循環依賴解決

     編輯:Java 綜合教學

核心原則:提早暴露 ObjectFactory

Spring 容器在建立單例 Bean 時,遵循「不等 Bean 完全初始化完成,就將建立 Bean 的 ObjectFactory 提早放入緩存」的原則。這項機制是解決循環依賴的關鍵基石。

三級緩存架構

Spring 使用三個 Map 協同管理單例 Bean 的不同生命週期狀態:

  • singletonObjects:成品 Bean 緩存,鍵為 Bean 名稱,值為完全初始化完成的 Bean 實例。
  • earlySingletonObjects:早期暴露的 Bean 緩存,用於循環依賴檢測,值為尚未完成屬性填充、初始化的原始實例。
  • singletonFactories:單例工廠緩存,值為 ObjectFactory,可延遲生成早期 Bean 參考。

getBean 獲取流程圖解

singletonObjects.get(beanName)          // 1. 嘗試從成品緩存獲取
    ↓ null
earlySingletonObjects.get(beanName)     // 2. 嘗試從早期緩存獲取(循環依賴場景)
    ↓ null
singletonFactories.get(beanName)        // 3. 從工廠緩存獲取 ObjectFactory
    ↓ getObject()
earlySingletonObjects.put(beanName, obj) // 4. 將生成的早期實例放入早期緩存
singletonFactories.remove(beanName)      // 5. 移除工廠,避免重複生成

FactoryBean 機制

實作 FactoryBean<T> 介面的類別,其 getObject() 回傳值才是真正被容器管理的 Bean。獲取方式:

  • ctx.getBean("book") → 取得 FactoryBean#getObject() 產出的物件。
  • ctx.getBean("&book") → 取得 FactoryBean 本身。

Bean 初始化完整階段

  1. 實例化:透過建構子或工廠方法建立原始物件。
  2. 屬性填充:依賴注入(DI),處理 @Autowired、XML <property> 等。
  3. Aware 回調:BeanNameAware、BeanFactoryAware、ApplicationContextAware 等。
  4. BeanPostProcessor 前置處理:postProcessBeforeInitialization。
  5. 初始化:InitializingBean#afterPropertiesSet()、@PostConstruct、XML init-method。
  6. BeanPostProcessor 後置處理:postProcessAfterInitialization(AOP 代理在此生成)。
  7. 註冊銷毀回調:DisposableBean、@PreDestroy、XML destroy-method。

循環依賴解決示意

假設 A 依賴 B,B 依賴 A:

  1. A 實例化 → 暴露 ObjectFactory 至 singletonFactories。
  2. A 屬性填充需 B → 啟動 B 建立流程。
  3. B 實例化 → 暴露 ObjectFactory。
  4. B 屬性填充需 A → 從 singletonFactories 取得 A 的早期參考 → 完成 B 初始化 → 放入 singletonObjects。
  5. 回到 A 完成屬性填充 → 初始化完成 → 放入 singletonObjects。

若關閉「允許循環依賴」(allowCircularReferences=false),步驟 4 將拋出 BeanCurrentlyInCreationException。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved