Spring IoC容器的初始化過程
Spring IoC(Inversion of Control,控制反轉(zhuǎn))容器的初始化是 Spring 框架啟動的核心過程,它負責創(chuàng)建和管理 Bean,以及處理 Bean 之間的依賴關系。
以下是 Spring IoC 容器初始化的詳細流程,結(jié)合 源碼關鍵類 和 核心步驟 拆解:
一、核心流程概覽
Spring IoC 容器初始化分為 2 大階段:
- 容器啟動準備:加載配置(XML/注解),解析成
BeanDefinition。 - Bean 實例化與依賴注入:根據(jù)
BeanDefinition創(chuàng)建 Bean,處理依賴、初始化。
二、詳細步驟(以ClassPathXmlApplicationContext為例)
1.容器啟動(構(gòu)造方法調(diào)用)
// 示例:創(chuàng)建 Xml 應用上下文
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
關鍵動作:
- 調(diào)用父類構(gòu)造方法,初始化 資源加載器(
ResourceLoader)和 ** Bean 工廠**(DefaultListableBeanFactory)。 - 記錄配置文件路徑(如
applicationContext.xml)。
2.加載配置文件(refresh()方法觸發(fā))
refresh() 是容器初始化的核心方法,定義在 AbstractApplicationContext 中,包含 13 個關鍵步驟(簡化版流程):
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 準備刷新:記錄啟動時間、標記活躍狀態(tài)、初始化屬性源
prepareRefresh();
// 2. 創(chuàng)建 Bean 工廠(若未創(chuàng)建),并加載 BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 準備 Bean 工廠:設置類加載器、后置處理器等
prepareBeanFactory(beanFactory);
try {
// 4. 子類擴展:允許子類修改 Bean 工廠(Spring Boot 常用)
postProcessBeanFactory(beanFactory);
// 5. 執(zhí)行 BeanFactoryPostProcessor:修改 BeanDefinition(如 PropertyPlaceholderConfigurer)
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注冊 BeanPostProcessor:用于 Bean 初始化前后增強(如 AutowiredAnnotationBeanPostProcessor)
registerBeanPostProcessors(beanFactory);
// 7. 初始化 MessageSource:國際化支持
initMessageSource();
// 8. 初始化 EventMulticaster:事件廣播器
initApplicationEventMulticaster();
// 9. 子類擴展:初始化特殊 Bean(如 Spring MVC 的 DispatcherServlet)
onRefresh();
// 10. 注冊事件監(jiān)聽器
registerListeners();
// 11. 實例化所有非延遲加載的單例 Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新:發(fā)布 ContextRefreshedEvent
finishRefresh();
} catch (BeansException ex) {
// 13. 異常處理:銷毀已創(chuàng)建的 Bean
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
3.關鍵步驟拆解
(1)加載BeanDefinition(步驟 2:obtainFreshBeanFactory)
作用:
- 解析配置文件(XML/注解),生成
BeanDefinition(包含 Bean 類名、作用域、依賴等信息)。
實現(xiàn):
- XML 配置:
XmlBeanDefinitionReader解析<bean>標簽,生成BeanDefinition。 - 注解配置:
ClassPathBeanDefinitionScanner掃描@Component、@Service等注解,生成BeanDefinition。
示例:
- XML 中的
<bean id="userService" class="com.example.UserService"/>會被解析為BeanDefinition,記錄userService的類名、作用域(默認單例)等。
(2)處理BeanFactoryPostProcessor(步驟 5:invokeBeanFactoryPostProcessors)
作用:
- 修改
BeanDefinition(在 Bean 實例化前)。
典型實現(xiàn):
PropertyPlaceholderConfigurer:替換BeanDefinition中的占位符(如${jdbc.url}→ 實際配置值)。ConfigurationClassPostProcessor:處理@Configuration類,解析@Bean方法。
示例:
- 配置文件中
<bean id="dataSource" url="${jdbc.url}"/>,PropertyPlaceholderConfigurer會將${jdbc.url}替換為application.properties中的實際值。
(3)注冊BeanPostProcessor(步驟 6:registerBeanPostProcessors)
作用:
- 注冊用于 Bean 初始化前后增強的處理器(如
AutowiredAnnotationBeanPostProcessor處理@Autowired)。
典型實現(xiàn):
AutowiredAnnotationBeanPostProcessor:解析@Autowired注解,實現(xiàn)依賴注入。AnnotationAwareAspectJAutoProxyCreator:實現(xiàn) AOP 代理,處理@Aspect切面。
(4)實例化單例Bean(步驟 11:finishBeanFactoryInitialization)
作用:
- 創(chuàng)建所有非延遲加載的單例 Bean(默認
lazy-init="false")。
實現(xiàn):
- 遍歷
BeanDefinition,調(diào)用getBean(beanName)創(chuàng)建 Bean。 - 處理依賴注入(
populateBean)、初始化(initializeBean)。
關鍵方法:
// AbstractBeanFactory.java
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType,
@Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 1. 檢查緩存:單例 Bean 先從緩存(singletonObjects)獲取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null) {
return (T) sharedInstance;
}
// 2. 創(chuàng)建 Bean 實例:調(diào)用構(gòu)造器/工廠方法
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 3. 依賴注入:填充屬性(@Autowired、<property>)
populateBean(beanName, mbd, instanceWrapper);
// 4. 初始化:調(diào)用 @PostConstruct、init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 5. 放入緩存(單例 Bean)
addSingleton(beanName, exposedObject);
return (T) exposedObject;
}
(5)發(fā)布ContextRefreshedEvent(步驟 12:finishRefresh)
作用:
- 通知容器已完成初始化,觸發(fā)
ApplicationListener處理。
示例:
- Spring MVC 的
DispatcherServlet會監(jiān)聽此事件,完成自身初始化(如加載 HandlerMapping)。
三、核心類與職責
| 類名 | 職責 |
|---|---|
| BeanDefinition | 存儲 Bean 的元數(shù)據(jù)(類名、作用域、依賴等) |
| BeanFactory | 基礎 IoC 容器接口,定義 Bean 的創(chuàng)建、查找方法 |
| ApplicationContext | 高級 IoC 容器接口(繼承 BeanFactory),支持 AOP、事件、國際化等 |
| AbstractApplicationContext | 實現(xiàn) ApplicationContext 核心邏輯(如 refresh() 方法) |
| DefaultListableBeanFactory | 默認 Bean 工廠,存儲 BeanDefinition,創(chuàng)建 Bean 實例 |
| BeanPostProcessor | Bean 初始化前后增強(如 AutowiredAnnotationBeanPostProcessor) |
| BeanFactoryPostProcessor | Bean 實例化前修改 BeanDefinition(如 PropertyPlaceholderConfigurer) |
四、總結(jié)
Spring IoC 容器初始化的核心是 refresh() 方法,通過以下步驟完成:
- 加載配置 → 解析為
BeanDefinition; - 處理
BeanFactoryPostProcessor→ 修改BeanDefinition; - 注冊
BeanPostProcessor→ 增強 Bean 初始化; - 實例化單例 Bean → 處理依賴注入、初始化;
- 發(fā)布事件 → 通知容器就緒。
理解這一過程,能清晰掌握 Spring 如何管理 Bean 的生命周期,以及 AOP、依賴注入的實現(xiàn)時機。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java中為什么start方法不能重復調(diào)用而run方法可以?
這篇文章主要介紹了Java中為什么start方法不能重復調(diào)用而run方法可以?帶著疑問一起學習下面文章的詳細內(nèi)容吧2022-05-05
基于SpringBoot和Vue3的博客平臺的用戶注冊與登錄功能實現(xiàn)
本教程將指導您如何使用Spring?Boot和Vue3實現(xiàn)用戶注冊與登錄功能。我們將使用Spring?Boot作為后端框架,Vue3作為前端框架,同時使用MySQL作為數(shù)據(jù)庫,感興趣的朋友可以參考一下2023-04-04

