Spring 深入——IoC 容器 02

IoC容器的實現學習——02目錄

  • IoC容器的實現學習——02
    • 回顧
    • IoC 容器的初始化過程:
      • BeanDefinition 的 Resource 定位
        • 小結:
回顧前面學習了 IoC 模式的核心概念,使用場景 , 以及 Spring 對 IoC
具體實現的兩種系列:BeanFactory 和 ApplicationContext
通過兩種系列的具體 IoC 容器來幫助我們了解了兩個不同的特點 , 以及面向不同的場景 。有利有弊,在開發中需要根據具體需求選擇合適的 IoC 具體實現 。
其中也通過對 Spring IoC 的具體實現的簡單分析,對 IoC 設計的有了初步的了解和想法 。那么現在就來開始了解 IoC 容器初始化的過程 。
IoC 容器的初始化過程:前面在學習 FileSystemXmlApplicationContext 的時候,構造方法中通過此類調用了 refresh() 方法 。IoC 容器的初始化實際上就是通過這個方法來啟動的,標志著 IoC 容器正式啟動 。
IoC 容器的啟動包括以下三個基本過程:
  1. BeanDefinition 資源的定位
  2. ~ 的載入
  3. ~ 的注冊
期間需要注意的是這是一個順序過程,同時指的是 IoC 容器的初始化,而 Bean 的依賴注入的實現 , 一般不包括其中,但是 BeanDefiniton 有一個 lazyinit 的屬性,用戶可以通過這個屬性改變 Bean 的依賴注入過程,eg:一般情況下 Bean 的注入需要在容器初始化之后,第一次調用 getBean() 時才會觸發 , 而通過 lazyinit 屬性可以讓 Bean 在 IoC 容器初始化時就預先完成了依賴注入 。
BeanDefinition 的 Resource 定位根據前面的學習 , 我們這一過程的表層應該不難知曉,就是通過定義一個 Resuorce 去定位容器使用的 BeanDefinition 。eg:ClassPathResource() 這個類就是在項目中的類路徑中尋找以文件形式存在的 BeanDefinition 。
應該注意的是,不能把 Resource 的定位 BeanDefinition 資源和 BD 的載入弄混淆了 。只是定位資源而已,此時 IoC 容器還不能直接使用這些信息,這些信息是交由 BeanDefinitionReader 來對這些信息進行 BD 的載入處理 。
相對于 DefaultListableBeanFactory 容器需要手動配置好特定的 Resource 讀取器,ApplicationContext 容器就準備好了一系列的讀取器 。
但是使用 DefaultListableBeanFactory 這種底層容器可以根據業務定制 IoC 容器的靈活性,有利有弊 。
還是通過 FileSystemXmlApplicationContext 這一具體容器來分析是如何完成 Resource 的定位過程 。
繼承體系:
Spring 深入——IoC 容器 02

文章插圖
主要兩個功能的源碼:
Spring 深入——IoC 容器 02

文章插圖
上圖表明了getResourceByPath()是實現 Resource 定位的方法 。但是并不是使用者調用的,查看該方法的調用鏈:
Spring 深入——IoC 容器 02

文章插圖
上圖標注了該方法最初是由 refresh() 方法觸發的,而 refresh() 是在構造器中調用的 。
我們需要通過這個方法來了解過程 。
構造器調用的是超類 AbstractApplicationContext 中的 refresh(),查看源碼:
public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {this.prepareRefresh();// 創建beanFactory以及掃描bean信息(beanDefinition) , 并通過BeanDefinitionRegistry 注冊到容器中 。ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();// 省略...}}obtainFreshBeanFactory() 源碼:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {this.refreshBeanFactory();// 省略...}refreshBeanFactory() 是一個抽象方法,有兩個具體的實現類:
  • AbstractRefreshableApplicationContext
  • GenericApplicationContext
在這里我們的 FSXAC 繼承了 AbstractRefreshableApplicationContext,所以我們看在這個類中 refreshBeanFactory() 的實現:
protected final void refreshBeanFactory() throws BeansException {//...try {DefaultListableBeanFactory beanFactory = this.createBeanFactory(); // 1beanFactory.setSerializationId(this.getId());this.customizeBeanFactory(beanFactory);this.loadBeanDefinitions(beanFactory);// 2///...}}我們抽出這兩行代碼進行分析:
  1. 創建 BeanFactory,以 DefaultListableBeanFactory 作為 IoC 容器 。
  2. BD 的載入相關啟動 。
我們到目前位置并沒有看到與之相關的 Resource 定位信息,只看到 BD 的載入啟動,所以針對

推薦閱讀