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