Spring IoC容器的初始化過程
Spring IoC(Inversion of Control,控制反轉(zhuǎn))容器的初始化是 Spring 框架啟動的核心過程,它負(fù)責(zé)創(chuàng)建和管理 Bean,以及處理 Bean 之間的依賴關(guān)系。
以下是 Spring IoC 容器初始化的詳細(xì)流程,結(jié)合 源碼關(guān)鍵類 和 核心步驟 拆解:
一、核心流程概覽
Spring IoC 容器初始化分為 2 大階段:
- 容器啟動準(zhǔn)備:加載配置(XML/注解),解析成
BeanDefinition。 - Bean 實(shí)例化與依賴注入:根據(jù)
BeanDefinition創(chuàng)建 Bean,處理依賴、初始化。
二、詳細(xì)步驟(以ClassPathXmlApplicationContext為例)
1.容器啟動(構(gòu)造方法調(diào)用)
// 示例:創(chuàng)建 Xml 應(yīng)用上下文
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
關(guān)鍵動作:
- 調(diào)用父類構(gòu)造方法,初始化 資源加載器(
ResourceLoader)和 ** Bean 工廠**(DefaultListableBeanFactory)。 - 記錄配置文件路徑(如
applicationContext.xml)。
2.加載配置文件(refresh()方法觸發(fā))
refresh() 是容器初始化的核心方法,定義在 AbstractApplicationContext 中,包含 13 個(gè)關(guān)鍵步驟(簡化版流程):
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 準(zhǔn)備刷新:記錄啟動時(shí)間、標(biāo)記活躍狀態(tài)、初始化屬性源
prepareRefresh();
// 2. 創(chuàng)建 Bean 工廠(若未創(chuàng)建),并加載 BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 準(zhǔn)備 Bean 工廠:設(shè)置類加載器、后置處理器等
prepareBeanFactory(beanFactory);
try {
// 4. 子類擴(kuò)展:允許子類修改 Bean 工廠(Spring Boot 常用)
postProcessBeanFactory(beanFactory);
// 5. 執(zhí)行 BeanFactoryPostProcessor:修改 BeanDefinition(如 PropertyPlaceholderConfigurer)
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注冊 BeanPostProcessor:用于 Bean 初始化前后增強(qiáng)(如 AutowiredAnnotationBeanPostProcessor)
registerBeanPostProcessors(beanFactory);
// 7. 初始化 MessageSource:國際化支持
initMessageSource();
// 8. 初始化 EventMulticaster:事件廣播器
initApplicationEventMulticaster();
// 9. 子類擴(kuò)展:初始化特殊 Bean(如 Spring MVC 的 DispatcherServlet)
onRefresh();
// 10. 注冊事件監(jiān)聽器
registerListeners();
// 11. 實(shí)例化所有非延遲加載的單例 Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新:發(fā)布 ContextRefreshedEvent
finishRefresh();
} catch (BeansException ex) {
// 13. 異常處理:銷毀已創(chuàng)建的 Bean
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
3.關(guān)鍵步驟拆解
(1)加載BeanDefinition(步驟 2:obtainFreshBeanFactory)
作用:
- 解析配置文件(XML/注解),生成
BeanDefinition(包含 Bean 類名、作用域、依賴等信息)。
實(shí)現(xiàn):
- XML 配置:
XmlBeanDefinitionReader解析<bean>標(biāo)簽,生成BeanDefinition。 - 注解配置:
ClassPathBeanDefinitionScanner掃描@Component、@Service等注解,生成BeanDefinition。
示例:
- XML 中的
<bean id="userService" class="com.example.UserService"/>會被解析為BeanDefinition,記錄userService的類名、作用域(默認(rèn)單例)等。
(2)處理BeanFactoryPostProcessor(步驟 5:invokeBeanFactoryPostProcessors)
作用:
- 修改
BeanDefinition(在 Bean 實(shí)例化前)。
典型實(shí)現(xiàn):
PropertyPlaceholderConfigurer:替換BeanDefinition中的占位符(如${jdbc.url}→ 實(shí)際配置值)。ConfigurationClassPostProcessor:處理@Configuration類,解析@Bean方法。
示例:
- 配置文件中
<bean id="dataSource" url="${jdbc.url}"/>,PropertyPlaceholderConfigurer會將${jdbc.url}替換為application.properties中的實(shí)際值。
(3)注冊BeanPostProcessor(步驟 6:registerBeanPostProcessors)
作用:
- 注冊用于 Bean 初始化前后增強(qiáng)的處理器(如
AutowiredAnnotationBeanPostProcessor處理@Autowired)。
典型實(shí)現(xiàn):
AutowiredAnnotationBeanPostProcessor:解析@Autowired注解,實(shí)現(xiàn)依賴注入。AnnotationAwareAspectJAutoProxyCreator:實(shí)現(xiàn) AOP 代理,處理@Aspect切面。
(4)實(shí)例化單例Bean(步驟 11:finishBeanFactoryInitialization)
作用:
- 創(chuàng)建所有非延遲加載的單例 Bean(默認(rèn)
lazy-init="false")。
實(shí)現(xiàn):
- 遍歷
BeanDefinition,調(diào)用getBean(beanName)創(chuàng)建 Bean。 - 處理依賴注入(
populateBean)、初始化(initializeBean)。
關(guān)鍵方法:
// 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 實(shí)例:調(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)。
三、核心類與職責(zé)
| 類名 | 職責(zé) |
|---|---|
| BeanDefinition | 存儲 Bean 的元數(shù)據(jù)(類名、作用域、依賴等) |
| BeanFactory | 基礎(chǔ) IoC 容器接口,定義 Bean 的創(chuàng)建、查找方法 |
| ApplicationContext | 高級 IoC 容器接口(繼承 BeanFactory),支持 AOP、事件、國際化等 |
| AbstractApplicationContext | 實(shí)現(xiàn) ApplicationContext 核心邏輯(如 refresh() 方法) |
| DefaultListableBeanFactory | 默認(rèn) Bean 工廠,存儲 BeanDefinition,創(chuàng)建 Bean 實(shí)例 |
| BeanPostProcessor | Bean 初始化前后增強(qiáng)(如 AutowiredAnnotationBeanPostProcessor) |
| BeanFactoryPostProcessor | Bean 實(shí)例化前修改 BeanDefinition(如 PropertyPlaceholderConfigurer) |
四、總結(jié)
Spring IoC 容器初始化的核心是 refresh() 方法,通過以下步驟完成:
- 加載配置 → 解析為
BeanDefinition; - 處理
BeanFactoryPostProcessor→ 修改BeanDefinition; - 注冊
BeanPostProcessor→ 增強(qiáng) Bean 初始化; - 實(shí)例化單例 Bean → 處理依賴注入、初始化;
- 發(fā)布事件 → 通知容器就緒。
理解這一過程,能清晰掌握 Spring 如何管理 Bean 的生命周期,以及 AOP、依賴注入的實(shí)現(xiàn)時(shí)機(jī)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(32)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
Java 實(shí)戰(zhàn)項(xiàng)目之疫情防控管理系統(tǒng)詳解
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)疫情防控管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11
Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)快速實(shí)現(xiàn)解析
這篇文章主要介紹了Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)快速實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Java StampedLock實(shí)現(xiàn)原理與最佳實(shí)踐記錄
本文介紹了Java 8引入的StampedLock,這是一種多模式同步控制組件,通過“戳”(stamp)標(biāo)識鎖的狀態(tài),支持寫鎖、悲觀讀鎖和樂觀讀三種模式,StampedLock在特定場景下能夠大幅提升系統(tǒng)性能,特別是在讀多寫少的場景中,感興趣的朋友跟隨小編一起看看吧2025-01-01
Spring中allowedOriginPatterns和allowedOrigins方法有何不同詳解
這篇文章主要給大家介紹了關(guān)于Spring中allowedOriginPatterns和allowedOrigins方法有何不同,allowedOriginPatterns和allowedOrigins都是用來設(shè)置允許跨域請求的來源,需要的朋友可以參考下2023-10-10
Idea工具中創(chuàng)建 SpringBoot工程及入門詳解
這篇文章主要介紹了Idea工具中創(chuàng)建 SpringBoot工程及入門分析詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02

