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

深入理解 Spring 系列四:BeanDefinition 裝載前奏曲 —— 從 refresh() 到 loadBeanDefinitions()

     編輯:Java 綜合教學

Spring IOC 容器啟動核心鏈路:BeanDefinition 裝載全流程啟動篇

Spring 容器啟動是一條精密的流水線。本文以 ClassPathXmlApplicationContext 為切入點,追蹤 refresh() 核心模板方法,深入 obtainFreshBeanFactory() → refreshBeanFactory() → loadBeanDefinitions(),揭示 BeanDefinition 裝載的完整調用鏈與關鍵決策點。

啟動入口:ClassPathXmlApplicationContext 構造器

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
    super(parent);
    setConfigLocations(configLocations); // 設置配置文件位置
    if (refresh) refresh(); // 核心啟動開關
}

refresh():容器初始化的總模板方法

定義於 AbstractApplicationContext,採用模板方法模式,完整步驟:

  1. prepareRefresh():記錄啟動時間、標記激活狀態、驗證必需屬性
  2. obtainFreshBeanFactory():創建 BeanFactory 並完成 BeanDefinition 裝載 (核心)
  3. prepareBeanFactory(beanFactory):配置工廠上下文 (類加載器、SpEL 解析器、後置處理器等)
  4. postProcessBeanFactory(beanFactory):子類擴展點,修改 BeanFactory 內部狀態
  5. invokeBeanFactoryPostProcessors(beanFactory):調用 BeanFactoryPostProcessor (如 PropertyPlaceholderConfigurer 解析 ${...})
  6. registerBeanPostProcessors(beanFactory):註冊 BeanPostProcessor (攔截 Bean 初始化前後)
  7. initMessageSource():初始化國際化消息源
  8. initApplicationEventMulticaster():初始化事件廣播器
  9. onRefresh():模板方法,Web 環境初始化 Servlet 容器等
  10. registerListeners():註冊監聽器
  11. finishBeanFactoryInitialization(beanFactory):實例化所有非懶加載單例 Bean
  12. finishRefresh():發布 ContextRefreshedEvent,清理緩存

obtainFreshBeanFactory():獲取裝載完畢的 BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory(); // 核心:創建並裝載 BeanDefinition
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    return beanFactory;
}

refreshBeanFactory():BeanFactory 重建與裝載入口

定義於 AbstractRefreshableApplicationContext,final 禁止覆蓋:

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans(); // 銷毀現有單例
        closeBeanFactory(); // 關閉舊工廠
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory(); // 創建核心工廠
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory); // 設置允許覆蓋、循環引用等策略
        loadBeanDefinitions(beanFactory); // 【核心入口】裝載 BeanDefinition
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    } catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source", ex);
    }
}

關鍵設計決策

  • DefaultListableBeanFactory:Spring 核心 Bean 容器,實現 ConfigurableListableBeanFactory,支撐完整 Bean 生命周期管理
  • customizeBeanFactory():配置 allowBeanDefinitionOverriding (默認 true)、allowCircularReferences (默認 true)
  • loadBeanDefinitions():抽象方法,由具體子類實現 (如 AbstractXmlApplicationContext 解析 XML、AnnotatedBeanDefinitionReader 掃描註解)

下一站:XML 解析與 BeanDefinition 註冊

loadBeanDefinitions(beanFactory) 在 AbstractXmlApplicationContext 中具體實現,將調用 XmlBeanDefinitionReader 解析 XML 文件,生成 BeanDefinition 對象並註冊到 DefaultListableBeanFactory 的 beanDefinitionMap 中。下一篇將深入剖析 XML 解析流程、命名空間處理、<bean> 元素到 BeanDefinition 的轉換邏輯。

總結

  1. refresh() 是容器啟動總模板,第 2 步完成 BeanDefinition 裝載
  2. obtainFreshBeanFactory() → refreshBeanFactory() → loadBeanDefinitions() 為核心調用鏈
  3. DefaultListableBeanFactory 是 BeanDefinition 的最終註冊倉庫
  4. loadBeanDefinitions() 為模板方法,具體解析策略由子類決定 (XML、註解、Groovy 等)

理解這條主幹鏈路,是掌握 Spring IOC 容器啟動機制、排查啟動失敗、擴展配置解析的關鍵地圖。

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