1. 程式人生 > 實用技巧 >Spring Ioc 容器啟動流程原始碼解析

Spring Ioc 容器啟動流程原始碼解析

做java開發四年了,很多時候都在想spring究竟是怎麼玩轉的,當對java有一定深入的理解,我們就需要對spring的原始碼進行解讀,原始碼的解讀過程個人覺得至少要看5遍以上才會不暈車,品讀其中的奧妙。

IOC(Inversion of Control)控制反轉:所謂控制反轉,就是把原先我們程式碼裡面需要實現的物件創 建、依賴的程式碼,反轉給容器來幫忙實現。

一、Spring 核心容器類圖

1、BeanFactory: spring Bean 的建立是典型的工廠模式,這一系列的 Bean 工廠,也即 IOC 容器為開發者管理物件 間的依賴關係提供了很多便利和基礎服務,在 Spring 中有許多的 IOC 容器的實現供使用者選擇和使用, 其相互關係如下:

2、BeanDefinition:SpringIOC 容器管理了我們定義的各種 Bean 物件及其相互的關係,Bean 物件在 Spring 實現中是 以 BeanDefinition 來描述的,其繼承體系如下:

3、BeanDefinitionReader:Bean 的解析過程非常複雜,功能被分的很細,因為這裡需要被擴充套件的地方很多,必須保證有足夠的靈 活性,以應對可能的變化。Bean 的解析主要就是對 Spring 配置檔案的解析。這個解析過程主要通過 BeanDefintionReader 來完成,最後看看 Spring 中 BeanDefintionReader 的類結構圖:

瞭解了spring容器的核心類,我現在就迫切的想知道,整個流程是如何串起來的,下面來看看spring webmvc 的啟動過程。

二、Web IOC 容器初體驗

1、web應用啟動的核心之一就是啟動了一個servlet來處理我們的請求,那我們熟悉的DispatchServlet 又是如何驅動spring的Ioc容器的,servlet啟動肯定是從init()方法開始,最終在FrameWorkServlet的configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac)方法中呼叫AbstractApplicationContext的refresh()方法,從而驅動Ioc容器初始化,如下圖:

2、refresh()方法:其中Ioc容器的初始化就在obtainFreshBeanFactory()方法中

publicvoidrefresh()throwsBeansException,IllegalStateException{
Objectvar1=this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor){
//1、呼叫容器準備重新整理的方法,獲取容器的當時時間,同時給容器設定同步標識
this.prepareRefresh();
//2、告訴子類啟動refreshBeanFactory()方法,Bean定義資原始檔的載入從
//子類的refreshBeanFactory()方法啟動
ConfigurableListableBeanFactorybeanFactory=this.obtainFreshBeanFactory();
//3、為BeanFactory配置容器特性,例如類載入器、事件處理器等
this.prepareBeanFactory(beanFactory);

try{
//4、為容器的某些子類指定特殊的BeanPost事件處理器
this.postProcessBeanFactory(beanFactory);
//5、呼叫所有註冊的BeanFactoryPostProcessor的Bean
this.invokeBeanFactoryPostProcessors(beanFactory);
//6、為BeanFactory註冊BeanPost事件處理器.
this.registerBeanPostProcessors(beanFactory);
//7、初始化資訊源,和國際化相關.
this.initMessageSource();
//8、初始化容器事件傳播器.
this.initApplicationEventMulticaster();
//9、呼叫子類的某些特殊Bean初始化方法
this.onRefresh();
//10、為事件傳播器註冊事件監聽器.
this.registerListeners();
//11、初始化所有剩餘的單例Bean
this.finishBeanFactoryInitialization(beanFactory);
//12、初始化容器的生命週期事件處理器,併發布容器的生命週期事件
this.finishRefresh();
}catch(BeansExceptionvar9){
if(this.logger.isWarnEnabled()){
this.logger.warn("Exceptionencounteredduringcontextinitialization-cancellingrefreshattempt:"+var9);
}

this.destroyBeans();
this.cancelRefresh(var9);
throwvar9;
}finally{
this.resetCommonCaches();
}

}
}

來看下spring 基於XML 的IOC容器初始化過程,最終BeanDefinition 被放到了DefaultListableBeanFactory 類中的private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256)中,建立過程如下圖:

在補充一張spring 基於annotion 的IOC容器初始化過程:

總結:Spring Ioc容器的初始化,不管通過何種途徑,spring mvc 的DispatchServlet 還是spring boot run()方法,最後都呼叫了AbstractApplicationContext 的refresh(),在通過obtainFreshBeanFactor()方法來初始化Ioc容器。

文章詳情請點選:http://www.xiaoyuge.com.cn/#/article/detail?articleId=68