淺析 Spring 啟動過程:從源碼到核心方法
- 一、Spring 注解方式啟動類 Demo
- 二、Spring 啟動過程源碼解析
- ?AnnotationConfigApplicationContext構造函數
- refresh()方法詳解
- 三、refresh()的核心方法/步驟
- obtainFreshBeanFactory() - 獲取Bean工廠
- prepareBeanFactory(beanFactory) - 配置 Bean 工廠
- invokeBeanFactoryPostProcessors() - 調用注冊的BeanFactoryPostProcessor實現類
- finishBeanFactoryInitialization() - 實例化、初始化所有剩余的單例 Bean【重要】【重要】【重要】

在 Java 企業級開發中,Spring 框架是最常用的基礎框架之一。了解 Spring 的啟動過程,對于理解 Spring 的工作原理、優化應用性能以及排查問題都有著至關重要的作用。本文將結合純 Spring 的注解方式啟動類,深入解讀 Spring 啟動過程的源碼,重點分析
refresh()
方法及其包含的關鍵步驟。
一、Spring 注解方式啟動類 Demo
首先,我們創建一個簡單的 Spring 項目,通過注解方式啟動 Spring 容器。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("com.coderzpw") // 掃描該路徑下的包
@Configuration
public class AppConfig {public static void main(String[] args) {// Spring容器啟動AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);// 可以在這里獲取Bean進行后續操作// 容器關閉applicationContext.close();}
}
在上述代碼中:
@Configuration
注解表明該類是一個配置類,用于替代傳統的 XML 配置文件。@ComponentScan("com.coderzpw")
注解用于掃描指定包及其子包下的所有@Component
、@Service
、@Repository
、@Controller
等注解標注的類,并將它們注冊為 Spring 容器中的 Bean。- 在
main
方法中,通過AnnotationConfigApplicationContext
來創建 Spring 應用上下文,傳入配置類AppConfig.class
,從而啟動 Spring 容器。
二、Spring 啟動過程源碼解析
當我們調用AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
時,Spring 的啟動過程便開始了。接下來我們深入源碼,一探究竟。
?AnnotationConfigApplicationContext構造函數
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {this();register(annotatedClasses);refresh();
}
上述代碼中:
this()
調用了無參構造函數,在無參構造函數中會初始化reader
和scanner
,用于讀取配置類和掃描 Bean。register(componentClasses)
方法將傳入的配置類注冊到容器中。- 最后調用的
refresh()
方法是 Spring 啟動過程的核心,它完成了 Spring 容器的初始化、Bean 的加載、配置的解析等一系列關鍵操作。
refresh()方法詳解
對 BeanPostProcessor、BeanFactoryPostProcessor不熟悉的同學可以查看下面文章:
【Spring BeanFactoryPostProcessor:機制解讀與代碼實踐】
【Spring BeanPostProcessor:機制解讀與代碼實踐】
refresh()
方法位于AbstractApplicationContext
類中,其源碼如下:
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 準備上下文環境,記錄啟動時間,標記活動狀態等prepareRefresh();// 告訴子類刷新內部bean工廠ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 準備bean工廠,設置一些屬性,如類加載器、表達式解析器等prepareBeanFactory(beanFactory);try {// 允許子類在bean工廠準備好后進行進一步的設置postProcessBeanFactory(beanFactory);// 執行BeanFactoryPostProcessor接口的實現類,在bean實例化之前修改bean的定義invokeBeanFactoryPostProcessors(beanFactory);// 注冊BeanPostProcessor接口的實現類,用于在bean實例化、配置和初始化前后進行處理registerBeanPostProcessors(beanFactory);// 初始化消息源,用于國際化等功能initMessageSource();// 初始化應用事件廣播器initApplicationEventMulticaster();// 留給子類初始化其他特殊bean的鉤子方法onRefresh();// 注冊監聽器到事件廣播器registerListeners();// 實例化所有剩余的非惰性單例beanfinishBeanFactoryInitialization(beanFactory);// 完成刷新過程,發布容器刷新完成事件等finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}
refresh()
方法主要包含 12 個步驟,每個步驟都承擔著不同的職責:
prepareRefresh();
【準備工作】
作用:在開始刷新容器之前,進行一些準備工作,如設置容器的啟動時間、標記容器為活躍狀態、清除緩存等。這是 IoC 容器啟動的前奏,為后續的初始化操作做好準備。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
【獲取Bean工廠】
作用:獲取或創建一個新的 BeanFactory 實例,BeanFactory 是 Spring IoC 容器的核心,負責管理 Bean 的定義和實例化。這個步驟是 IoC 容器啟動的基礎,后續的 Bean 加載和創建都依賴于BeanFactory。(重要:XML配置形勢下,加載BeanDefinition就是在這個步驟,具體方法步驟:obtainFreshBeanFactory
->refreshBeanFactory
->loadBeanDefinitions
)prepareBeanFactory(beanFactory);
【配置 Bean 工廠】【為BeanFactory做基礎的配置】
作用:對獲取到的 BeanFactory 進行一些默認配置,如設置類加載器、添加默認的Bean 后置處理器(例如ApplicationContextAwareProcessor、ApplicationListenerDetector)、設置表達式解析器等。這些配置會影響后續 Bean 的創建和初始化過程。postProcessBeanFactory(beanFactory);
【后置處理 Bean 工廠】【子類做后置擴展處理】
作用:允許子類對 BeanFactory 進行額外的后置處理,例如注冊自定義的 BeanPostProcessor 或 BeanFactoryPostProcessor。這為開發者提供了擴展 IoC 容器功能的機會。invokeBeanFactoryPostProcessors(beanFactory);
【調用注冊的BeanFactoryPostProcessor實現類】
作用:調用所有注冊的 BeanFactoryPostProcessor 實現類,這些處理器可以在 Bean 定義加載完成后、Bean 實例化之前對 Bean 定義進行修改。通過這個步驟,開發者可以動態地修改 Bean 的定義信息。registerBeanPostProcessors(beanFactory);
【注冊 BeanPostProcessor的實現類】【只注冊、不調用】
作用:注冊所有的 BeanPostProcessor實現類,這些處理器會在Bean實例化、配置和初始化前后進行額外的處理。例如,AutowiredAnnotationBeanPostProcessor可以處理@Autowired注解,實現自動裝配功能initMessageSource();
【初始化消息源】
作用:初始化消息源,用于支持國際化和消息解析。這在需要處理多語言的應用程序中非常有用。initApplicationEventMulticaster();
【初始化應用[事件廣播器]】
[事件廣播器]:負責將事件廣播給所有注冊的監聽器。
[事件發布者(ApplicationEventPublisher)]:負責發布事件
[事件監聽器(ApplicationListener)]:負責監聽特定類型的事件
作用:初始化應用事件廣播器,用于發布和監聽應用程序中的事件。Spring 的事件機制允許組件之間進行松耦合的通信。onRefresh();
【留給子類擴展】【空實現】【子類特定的刷新操作】
作用:允許子類實現特定的刷新邏輯,例如在 WebApplicationContext 中,會創建和初始化 Servlet 上下文。registerListeners();
【注冊監聽器】
作用:注冊應用程序中的事件監聽器,這些監聽器會監聽由事件廣播器發布的事件,并執行相應的處理邏輯。finishBeanFactoryInitialization(beanFactory);
【實例化所有剩余的單例 Bean】【Bean 實例化、初始化、BeanPostProcessor的執行】
作用:實例化所有剩余的單例 Bean,這是 IoC 容器啟動的核心步驟之一。在這個過程中,BeanFactory 會根據 Bean 定義創建 Bean 實例,并進行依賴注入和初始化操作。finishRefresh();
【完成刷新】
作用:完成容器的刷新工作,清除緩存、發布容器刷新完成事件等。此時,IoC 容器已經完全啟動并可以正常使用。
三、refresh()的核心方法/步驟
obtainFreshBeanFactory() - 獲取Bean工廠
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory(); // 觸發BeanDefinition加載return getBeanFactory();
}
obtainFreshBeanFactory()
是Spring容器啟動流程中的核心方法,其核心性體現在:
- BeanFactory生命周期起點:負責創建或刷新BeanFactory實例,是IoC容器誕生的起點
- 配置加載入口:觸發XML配置的解析流程,將配置轉化為可操作的
BeanDefinition
對象
BeanDefinition加載流程解析
1. 傳統Spring項目(XML配置為例)
核心步驟:
refreshBeanFactory()
:銷毀舊容器 → 創建DefaultListableBeanFactory
→ 加載BeanDefinition
loadBeanDefinitions()
:通過XmlBeanDefinitionReader
解析XML文件,生成BeanDefinition
并注冊
源碼示例:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// ....initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);
}
2. SpringBoot項目(注解驅動)
- 實現差異:
- 本質使用
GenericApplicationContext
代替AbstractRefreshableApplicationContext
obtainFreshBeanFactory()
僅設置序列化ID,不執行配置加載
- 本質使用
- 實際加載入口:
ConfigurationClassPostProcessor
(后置處理器)掃描@Configuration
類@ComponentScan
注解觸發包掃描,動態注冊BeanDefinition
prepareBeanFactory(beanFactory) - 配置 Bean 工廠
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 告訴內部 Bean 工廠使用上下文的類加載器等。beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 注冊ApplicationContextAwareProcessor (ApplicationContextAwareProcessor負責處理實現了ApplicationContextAware的類)beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));// // 注冊早期后處理器,用于將內部 bean 檢測為 ApplicationListeners。beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// ...// 注冊默認的 環境Beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}
}
核心配置:
- 設置類加載器
- 添加默認的Bean 后置處理器(例如
ApplicationContextAwareProcessor
、ApplicationListenerDetector
) - 注冊默認的 環境bean
invokeBeanFactoryPostProcessors() - 調用注冊的BeanFactoryPostProcessor實現類
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 【核心】調用 BeanFactoryPostProcessorsPostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)// ...
}
進入invokeBeanFactoryPostProcessors
:
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// 【 1. 處理所有 BeanDefinitionRegistryPostProcessor(子接口)】if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =new LinkedList<BeanDefinitionRegistryPostProcessor>();// 分階段處理:PriorityOrdered → Ordered → 普通實現// 執行 PriorityOrdered invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);// 執行 OrderedinvokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);// 執行 普通實現invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// ...// 【 2. 處理所有 BeanFactoryPostProcessor】// 分階段處理:PriorityOrdered → Ordered → 普通實現List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();List<String> orderedPostProcessorNames = new ArrayList<String>();List<String> nonOrderedPostProcessorNames = new ArrayList<String>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// 執行 PriorityOrdered invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 執行 OrderedinvokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 執行 普通實現invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// ...
}
具體執行方法:invokeBeanFactoryPostProcessors
/*** 調用給定的BeanFactoryPostProcessor bean。*/
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {// 執行具體的postProcessBeanFactory方法postProcessor.postProcessBeanFactory(beanFactory);}
}
其中ConfigurationClassPostProcessor
是BeanFactoryPostProcessor
的子類,會在該階段執行其后置處理邏輯。負責解析 @Configuration
類及其注解(如 @ComponentScan
、@Bean
),動態注冊新的 BeanDefinition
ConfigurationClassPostProcessor
核心功能:
- 掃描配置類: 識別
@Configuration
類,解析其上的@ComponentScan
、@Import
等注解 - 處理條件注解: 根據
@Conditional
注解判斷是否注冊對應的BeanDefinition
finishBeanFactoryInitialization() - 實例化、初始化所有剩余的單例 Bean【重要】【重要】【重要】
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// ...// 實例化所有剩余的 (非 lazy-init) 單例。【核心】【重要】【bean實例化 -> 屬性填充 -> 初始化】beanFactory.preInstantiateSingletons();
}
finishBeanFactoryInitialization() 方法核心作用總結:
- 初始化基礎服務
- 設置類型轉換服務(
ConversionService
),處理@Value
和屬性注入的類型轉換
- 設置類型轉換服務(
- 凍結 Bean 配置
- 調用
freezeConfiguration()
,停止修改BeanDefinition
,確保后續實例化過程的線程安全
- 調用
- 實例化非懶加載單例 Bean
- 遍歷所有
BeanDefinition
,觸發getBean()
實例化非抽象、單例且非懶加載的 Bean - 特殊處理
FactoryBean
:根據SmartFactoryBean.isEagerInit()
判斷是否立即生成目標對象
- 遍歷所有
- 初始化回調與擴展
- 觸發
SmartInitializingSingleton.afterSingletonsInstantiated()
,在所有單例創建完成后執行自定義邏輯 - 處理
LoadTimeWeaverAware
接口,支持類加載期字節碼增強(如 AspectJ LTW)
- 觸發
- 資源回收與優化
- 釋放臨時類加載器(
TempClassLoader
),避免內存泄漏
- 釋放臨時類加載器(
該方法涉及 Spring IoC 最復雜的實例化階段,包括 bean的實例化、屬性填充(解決循環依賴)、BeanPostProcesser的前置處理(部分Aware處理邏輯)、bean的初始化、BeanPostProcesser的后置處理(AOP 代理的生成時機)等細節
一篇文章是講解不清楚finishBeanFactoryInitialization()的,請期待后續總結 ?ヽ(°▽°)ノ?