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

Spring ApplicationContext 核心流程源碼解讀:從 refresh() 到 Bean 就緒

     編輯:Java 綜合教學

ApplicationContext 定位

ApplicationContext 繼承 BeanFactory,擴充了事件發布、國際化、資源載入、掃描註冊等企業級功能。其核心邏輯集中在 refresh() 方法,該方法同步執行,確保容器啟動過程的原子性。

refresh() 完整流程圖解

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();                         // 1. 準備:啟動時間、活躍標記、屬性源初始化
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 2. 獲取/建立 BeanFactory
        prepareBeanFactory(beanFactory);          // 3. 配置 BeanFactory 標準特性
        try {
            postProcessBeanFactory(beanFactory);  // 4. 子類後處理 BeanFactory
            invokeBeanFactoryPostProcessors(beanFactory); // 5. 執行 BeanFactoryPostProcessor(如 PropertyPlaceholderConfigurer)
            registerBeanPostProcessors(beanFactory);      // 6. 註冊 BeanPostProcessor(AOP、自動代理等)
            initMessageSource();                  // 7. 國際化 MessageSource
            initApplicationEventMulticaster();    // 8. 事件廣播器
            onRefresh();                          // 9. 子類擴充點(Web 容器啟動 Servlet 等)
            registerListeners();                  // 10. 註冊 ApplicationListener
            finishBeanFactoryInitialization(beanFactory); // 11. 實例化所有非懶加載單例
            finishRefresh();                      // 12. 發布 ContextRefreshedEvent
        } catch (BeansException ex) {
            destroyBeans(); cancelRefresh(ex); throw ex;
        } finally {
            resetCommonCaches();
        }
    }
}

關鍵階段深度剖析

prepareRefresh():環境就緒

  • 設定 startupDate、active=true、closed=false。
  • initPropertySources():預留擴充點,子類可注入額外屬性源(如從配置中心拉取)。
  • validateRequiredProperties():檢查必要屬性是否可解析。
  • 初始化 earlyApplicationEvents 集合,收集廣播器就緒前的早期事件。

prepareBeanFactory():BeanFactory 標準化配置

  • 設定 ClassLoader、BeanExpressionResolver(支援 SpEL #{...})、PropertyEditorRegistrar(類型轉換,如 String→Date)。
  • 註冊 ApplicationContextAwareProcessor,自動注入 ApplicationContext 等 Aware 介面。
  • 忽略自動裝配的介面:ResourceLoaderAware、ApplicationEventPublisherAware 等。
  • 註冊可解析依賴:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext 本身。
  • 偵測 LoadTimeWeaver(AspectJ LTW 支援)。
  • 註冊環境相關單例:environment、systemProperties、systemEnvironment。

SpEL 表達式語言

Spring Expression Language(獨立模組,僅依賴 core),支援運行時構建複雜表達式、存取物件圖屬性、呼叫方法。常見於 @Value("#{systemProperties['os.name']}") 或 XML <property value="#{bean.method()}" />。

PropertyEditor 與 CustomEditorConfigurer

Spring 內建類型轉換器,若需自定義(如 String→Date 格式),可透過 CustomEditorConfigurer 註冊:

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
        <map>
            <entry key="java.util.Date">
                <bean class="com.xxx.MyDateEditor">
                    <property name="format" value="yyyy-MM-dd HH:mm:ss"/>
                </bean>
            </entry>
        </map>
    </property>
</bean>

或實作 PropertyEditorRegistrar 統一註冊多個編輯器。

invokeBeanFactoryPostProcessors():容器級後處理

典型應用:PropertyPlaceholderConfigurer 解析 ${...} 佔位符,合併屬性檔、轉換屬性、處理屬性值,供後續 Bean 實例化使用。

國際化與事件機制

  • initMessageSource():載入 messageSource Bean(固定 ID),支援 ResourceBundleMessageSource 讀取 message_en.properties、message_zh_CN.properties。
  • initApplicationEventMulticaster():建立 SimpleApplicationEventMulticaster,支援同步/非同步廣播。
  • registerListeners():掃描 ApplicationListener Bean 並註冊,同時發布早期收集的事件。

擴充建議

一般不直接實作 ApplicationContext(介面過多),建議繼承 ClassPathXmlApplicationContext 並覆寫 initPropertySources()、onRefresh() 等保護方法,實現自定義啟動邏輯。

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