spring源碼分析系列5:ApplicationContext的初始化與Bean生命周期

  • 2019 年 10 月 17 日
  • 筆記

回顧Bean與BeanDefinition的關係. BeanFactory容器. ApplicationContext上下文.

首先總結下:

  1. 開發人員定義Bean資訊:分為XML形式定義;註解式定義
  2. ApplicationContext搜集Bean的定義;存儲到BeabFactory容器的中。
  3. BeanFactory根據這些BeanDefinition創建Bean.快取起來供我們使用。

[開發人員]--標註-->[Bean定義] ---搜集 -->[BeanDefinition]---創建-->[Bean]

此節:我們從程式碼層面分析此過程.

refresh()

refresh()方法描述了ApplicationContext的初始化過程,這個過程大部分工作都是執行Bean定義到BeanDefinition到Bean的過程。

refresh()大致可以分為五部分來看:

1.BeanDefinition入庫前準備階段:

  • prepareRefresh();:主要工作環境屬性的初始化,校驗。
  • obtainFreshBeanFactory();: 準備一個beanFactory()(註:XML配置形式的Bean大多在此時執行了搜集入庫)
  • prepareBeanFactory(beanFactory);:配置beanFactory的相關資訊,包括類載入;類載入器,解析器,需要的依賴和需要忽略的依賴,早期的Bean級別後處理器,創建環境相關Bean
  • postProcessBeanFactory(beanFactory); 該方法只要是針對web類型的上下文中的增加配置beanFactory的相關屬性。

總的的來說,此階段是在做beanFactory的相關配置。

2.BeanDefinition搜集入庫階段:

  • invokeBeanFactoryPostProcessors(beanFactory):此方法主要了搜集註解型BeanDefinition,註冊這些BeanDefinition, 執行BeanFactoryPostProcessor.postProcessBeanFactory()方法,做入庫時的修改操作。

此過程非常的精妙。由PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()全全負責,
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法上本質就幹了兩件事:

  1. 執行註冊型BeanFactoryPostProcessor:此時有個重要的ConfigurationClassPostProcessor註冊器,此類會將註解配置型的BeanDefinition找到,並註冊到BeanFactory中。
  2. 執行普通類型的BeanFactoryPostProcessor:做入庫的修改操作。

3.部分特殊功能的Bean提前創建:
此階段把少部分特殊用處的BeanDefinition先創建Bean供使用。

  • registerBeanPostProcessors(beanFactory);實例化一些BeanPostProcessor為將來的BeanDefinition生成Bean時做準備。。
  • initMessageSource(); 初始化ApplicationContext的國際化相關組件Bean,消息綁定,消息解析
  • initApplicationEventMulticaster();:初始化廣播器組件Bean,用於初始化過程中廣播階段性事件。
  • onRefresh(); 初始化子類中特殊Beans(也算是一個擴展點)
  • registerListeners();:將容器中的監聽器Bean,設置到廣播器中去。

4.普通BeanDefinition生成Bean階段
此階段是大部分BeanDefinition生成Bean的階段。

  • finishBeanFactoryInitialization(beanFactory);:
    此過程,就是上篇文章說的 ,applicationContext上下文觸發beanFactory內部的BeanDefinition創建Bean。

    我們想像一個場景: 先往一個機器內先放入原料BeanDefinition後,然後再按下開關開始製造.ApplicationContext在此處就好比按下開關.開始Bean的製造,Bean的製作過程是一條流水線,流水線上有不同類型的機器對原料做不同的處理,最終得到Bean

ApplicationContext調用DefaultListableBeanFactory.preInstantiateSingletons()開始觸發Bean的創建:

doGetBean:

  1. 首先檢查倉庫中是否已經創建過此Bean,有取出來
  2. 沒有就準備走流水線創建Bean創建.
  3. 創建前先檢查物料有沒有?有,標記當前Bean在創建中
  4. 檢查是否有依賴,有的話,先去載入創建依賴Bean. 又回到了1
  5. 判斷作用域,上createBean()流水線準備執行。

doGetBean->createBean:

  1. 載入Bean的Class類
  2. 驗證以及準備需要覆蓋的方法

doGetBean->createBean->代理對象: 返回代理對象

  1. 創建代理對象:給BeanPostProcessors 一個機會來返回代理對象來代替真正的實例(此處返回的是針對自定義TargetSource的Bean)

doGetBean->createBean->doCreateBean:沒有創建自定義代理對象繼續執行

  1. 使用合適的實例化策略來創建Bean(工廠方法、構造函數自動注入、簡單初始化),並得到Bean包裝類BeanWrapper對象。
  2. 調用BeanDefinitionPostProcessor後置處理器,修改 BeanDefinition
  3. 解決單例模式的循環依賴:解決辦法是儘早暴露Bean的引用到快取中,讓其他對象可以能引用到他
  4. populateBean設置bean的屬性
  5. initializeBean:

doGetBean->createBean->doCreateBean->initializeBean 實例化Bean

  1. invokeAwareMethods:執行_awre類型的方法
  2. applyBeanPostProcessorsBeforeInitialization執行BeanPostProcessor的前置方法
  3. invokeInitMethods: 執行InitializingBean介面的afterPropertiesSet ,invokeCustomInitMethod執行自定義的init-method方法
  4. applyBeanPostProcessorsAfterInitialization:執行BeanPostProcessor的後置方法
  5. 返回Bean. 至此BeanDefinition到Bean的生產過程完成。

5.applicationContext的收尾階段

  • finishRefresh();
    收尾階段其實也算是applicationContext的擴展點。Lifecycle介面生命周期介面,

    (1.首先會從Bean容器中獲取LifecycleProcessor類型的Bean,如果沒有則創建一個默認的DefaultLifecycleProcessor。LifecycleProcessor是幹嘛用的?LifecycleProcessor是用來處理Lifecycle介面的bean的。

    (2.使用獲得LifecycleProcessor執行實現了Lifecycle介面的Bean的start()方法

    (3.發布上下文初始化完成事件

    (4.Participate in LiveBeansView MBean, if active.不是很清楚幹嘛的。

Bean的生命周期

看完了refresh()方法。我們再來總結下Bean的生命周期。

用一張圖表示
在这里插入图片描述

Bean的完整生命周期分為四個階段:

  1. 第一階段:實例化階段。
    從Bean定義的收集到BeanDefinition的入庫順序執行
    BeanDefinitionRegistryPostProcessor註冊處理器,註冊一些BeanDefinition
    BeanFactoryPostProcessor,對入庫的BeanDefinition進行定義的修改。
    BeanWrapper的產生,BeanWrapper是Bean的早期產品。
    populateBean()執行屬性的設置
    總結:此階段是BeanDefinition->BeanWrapper ,各種屬性的設置

  2. 第二階段:初始化階段:主要是執行各種初始化方法
    invokeAwareMethods(beanName, bean);執行Aware屬性的相關設置。
    BeanPostProcessor.postProcessBeforeInitialization前置方法的執行,
    如果實現了InitializingBean.afterPropertiesSet()則執行此方法
    執行自定義的initMethod方法。
    BeanPostProcessor.postProcessBeforeInitialization後置方法的執行,

  3. 第三階段:使用階段
    getBean從容器的快取中取出Bean

  4. 第四階段:銷毀階段
    執行DisposableBean.distroy方法
    執行自定義detry-method

總結:

整個spring初始化過程可以看做是

  • 物料(BeanDefinition)的搜集入庫(BeanFactory)
  • 生產線(getBean())取出物料創建成品(Bean)
  • 成品(Bean)入庫(BeanFactory)

歡迎大家關注我的公眾號【源碼行動】,最新個人理解及時奉送。
在这里插入图片描述

Tags: