spring源碼:核心組件(li)


一、AOP實現

  Spring代理對象的產生:代理的目的是調用目標方法時我們可以轉而執行InvocationHandler類的invoke方法,所以如何在InvocationHandler上做文章就是Spring實現Aop的關鍵所在。Spring的代理類正是繼承了Factory Bean的ProxyFactoryBean,ProxyFactoryBean之所以特別就在它可以讓你自定義對象的創建方法。當然代理對象要通過Proxy類來動態生成。下面是Spring創建的代理對象的時序圖:Spring創建了代理對象后,當你調用目標對象上的方法時,將都會被代理到InvocationHandler類的invoke方法中執行。在這里JdkDynamicAopProxy類實現了InvocationHandler接口。

  Spring是調用攔截器,Spring調用攔截器的時序圖如下:

二、IOC容器的初始化過程

  Spring提供了一個BeanFactory的基本實現,XmlBeanFactory同樣的通過使用模板模式來得到對IOC容器的抽象-AbstractBeanFactory,DefaultListableBeanFactory這些抽象類為其提供模板服務。其中通過resource 接口來抽象bean定義數據,對Xml定義文件的解析通過委托給XmlBeanDefinitionReader來完成。簡單的演示IOC容器的創建過程:

ClassPathResource res = new ClassPathResource("beans.xml"); 
DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); 
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);  

這些代碼演示了以下幾個步驟:

  1. 創建IOC配置文件的抽象資源
  2. 創建一個BeanFactory
  3. 把讀取配置信息的BeanDefinitionReader,這里是XmlBeanDefinitionReader配置給BeanFactory
  4. 從定義好的資源位置讀入配置信息,具體的解析過程由XmlBeanDefinitionReader來完成,這樣完成整個載入bean定義的過程。我們的IoC容器就建立起來了。

實際上,Spring的IoC容器初始化包括:Bean定義資源文件的定位、載入和注冊3個基本過程。 

  1. Bean定義資源文件的定位: Bean定義資源文件定位由ResourceLoader通過統一的Resource接口來完成,Resource接口將各種形式的Bean定義資源文件封裝成統一的、IoC容器可進行載入操作的對象。 通過ResourceLoader來完成資源文件位置的定位,DefaultResourceLoader是默認的實現,同時上下文本身就給出了ResourceLoader的實現,可以從類路徑,文件系統, URL等方式來定為資源位置。如果是XmlBeanFactory作為IOC容器,那么需要為它指定bean定義的資源,也就是說bean定義文件時通過抽象成Resource來被IOC容器處理的。
  2. Bean定義資源文件的載入: Bean定義資源文件載入的過程是將Bean定義資源文件中配置的Bean轉換成IoC容器中所管理Bean的數據結構形式。Spring IoC中管理 的Bean的數據結構是BeanDefinition,BeanDefinition是POJO對象在IoC容器中的抽象。容器通過BeanDefinitionReader來完成定義信息的解析和Bean信息的注冊,往往使用的是XmlBeanDefinitionReader來解析bean的xml定義文件,實際的處理過程是委托給BeanDefinitionParserDelegate來完成的,從而得到bean的定義信息,這些信息在Spring中使用BeanDefinition對象來表示 。這個名字可以讓我們想到loadBeanDefinition,RegisterBeanDefinition這些相關的方法,他們都是為處理BeanDefinitin服務的。
  3. Bean定義的注冊:IoC容器解析得到BeanDefinition以后,需要把它在IOC容器中注冊,這由IOC實現 BeanDefinitionRegistry接口來實現。注冊過程就是在IOC容器內部維護的一個HashMap來保存得到的 BeanDefinition的過程。這個HashMap是IoC容器持有bean信息的場所,以后對bean的操作都是圍繞這個HashMap來實現的。

三、Spring IOC容器的設計

兩條主線:第一條主線:從接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一條主要的BeanFactory設計路線。

  1. BeanFactory接口定義了基本的IoC容器的規范。基本定義了獲取bean和獲取判斷bean全局范圍類型等。
  2. HierarchicalBeanFactory,提供了getParentBeanFactory,使BeanFactory具備了雙親IoCring容器管理能力,和containsLocalBean(String name)兩個方法。
  3. ConfigurableBeanFactory,主要定義了一些對BeanFactory的配置功能。

  第二條主線:第二條接口設計主線是,以ApplicationContext應用上下文接口為核心的接口設計,這里涉及的主要接口設計有,從BeanFactory到ListableBeanFactory,再到ApplicationContext,再到ConfigurableApplicationContext或WebApplicationContext。

  1. ListableBeanfactory接口繼承了 BeanFactory 的同時,提供了列舉 Bean 的功能,他能夠列舉當前 BeanFactory 加載的所有 Bean :列舉所有 Bean 的名字或者滿足某種類型的 Bean 的名字,根據類型返回所有 Bean 對象 , 等。但是它無法獲取上層 BeanFactory 加載的單例 Bean 。
  2. HierarchicalBeanFactory 比較簡單,它主要是提供父 BeanFactory 的功能,通過它能夠獲取當前 BeanFactory 的父工廠( PS: 若在 A 工廠啟動並加載 Bean 之前, B 工廠先啟動並加載了,那 B 就是 A 的父工廠),這樣就能讓當前的 BeanFactory 加載父工廠加載的 Bean 了,彌補了 ListableBeanfactory 欠缺的功能。
  3. ConfigurableBeanFactory 就是在 HierarchicalBeanFactory 的基礎上增加了可配置的功能,包括注冊別名、注冊單例等,設置 Classloader 、是否緩存 Bean Metadata 、設置 TypeConverter 、 BeanPostProcessor 、配置 Bean 依賴等。 PS:ConfigurableBeanFactory 還繼承了 SingletonBeanRegistry 定義了一個注冊singleton bean的容器,用來定義為用來共享的 bean 實例的注冊表。此接口可以被BeanFactory的實現實現,用來形成一個統一管理singleton bean的風格。
  4. AutowireCapableBeanFactory ,主要是提供自動 Bean 自動綁定 ( 或者說自動裝配 ) 功能。例如根據自動裝配策略 new 一個 bean ,為已有的 bean 裝配屬性依賴;還有創建 bean 之后的回調功能,為 bean 設置 name 、 bean factory 、 bean post processor 等;將 bean post processor 應用到 bean 的初始化,等等。
  5. MessageSource用來支持國際化。
  6. ResourceLoader接口用於實現不同的Resource加載策略,即將不同Resource實例的創建交給ResourceLoader來計算。在ResourceLoader接口中,主要定義了一個方法:getResource(),它通過提供的資源location參數獲取Resource實例。
  7. ApplicationEventPublisher接口作為事件發布者,並且ApplicationContext實現了這個接口,擔當起了事件發布者這一角色。

四、Spring總體架構

 

  Spring總共有十幾個組件,但是真正核心的組件只有三個:Core、Context和Beans。它們構建起了整個Spring的骨骼架構。沒有它們就不可能有AOP、Web等上層的特性功能。

  1. Spring就是面向Bean的編程(BOP,Bean Oriented Programming),Bean在Spring 中才是真正的主角。Bean在Spring中作用就像Object對OOP的意義一樣,沒有對象的概念就像沒有面向對象編程,Spring中沒有Bean也就沒有Spring存在的意義。Spring解決了一個非常關鍵的問題是把對象之間的依賴關系轉而用配置文件來管理,也就是依賴注入機制。而這個注入關系在一個叫Ioc容器中管理,那Ioc容器中存放的就是被Bean包裹的對象。Spring正是通過把對象包裝在 Bean中而達到對這些對象管理以及一些列額外操作的目的。
  2. Context就是一個Bean關系的集合,這個關系集合又叫Ioc容器。如果把Bean比作一場演出中的演員的話,那Context就是這場演出的舞台背景。
  3. Core就是發現、建立和維護每 個Bean之間的關系所需要的一些列的工具,從這個角度看來,Core這個組件叫Util更能理解一些。

五、核心組件

  Bean組件在Spring的org.springframework.beans包下。這個包下的所有類主要解決了三件事:Bean的定義、Bean 的創建以及對Bean的解析。

  如上圖所示:Bean的創建時典型的工廠模式,他的頂級接口是BeanFactory,下圖是這個工廠的繼承層次關系。

  如上圖所示:Bean的定義主要有BeanDefinition描述,如下圖說明了這些類的層次關系。Bean的定義就是完整的描述了在Spring的配置文件中你定義的節點中所有的信息,包括各種子節點。當Spring成功解析完定義的一個節點后,在Spring的內部就被轉化成BeanDefinition對象。

  如上圖所示:Bean的解析過程非常復雜,功能被分的很細,因為這里需要被擴展的地方很多,必須保證有足夠的靈活性,以應對可能的變化。Bean的解析主要就是對Spring配置文件的解析。這個解析過程主要通過下圖中的類完成。

 

  Context組件:Context在Spring的org.springframework.context包下。ApplicationContext是Context的頂級父類,他除了能標識一個應用環境的基本信息外,他還繼承了五個接口,這五個接口主要是擴展了Context的功能。下面是Context的類結構圖,從上圖中可以看出ApplicationContext繼承了BeanFactory,這也說明了Spring容器中運行的主體對象是Bean。 

ApplicationContext的子類主要包含兩個方面:

  1. ConfigurableApplicationContext表示該Context是可修改的,也就是在構建Context中用戶可以動態添加或修改已有的配置信息,它下面又有多個子類,其中最經常使用的是可更新的Context,即 AbstractRefreshableApplicationContext類。
  2. WebApplicationContext顧名思義,就是為web准備的Context他可以直接訪問到ServletContext,通常情況下,這個接口使用的少。

再往下分就是按照構建Context的文件類型,接着就是訪問Context的方式。這樣一級一級構成了完整的Context等級層次。總體來說ApplicationContext必須要完成以下幾件事:

  1. 標識一個應用環境
  2. 利用BeanFactory創建Bean對象
  3. 保存對象關系表
  4. 能夠捕獲各種事件

Context作為Spring的Ioc容器,基本上整合了Spring的大部分功能,或者說是大部分功能的基礎。

 

  Core組件,Core組件作為Spring的核心組件,他其中包含了很多的關鍵類,其中一個重要組成部分就是定義了資源的訪問方式。下圖是Resource相關的類結構圖。 

  Resource接口封裝了各種可能的資源類型,也就是對使用者來說屏蔽了文件類型的不同。對資源的提供者來說,如何把資源包裝起來交給其他人用這也是一個問題,Resource 接口繼承了InputStreamSource接口,這個接口中有個getInputStream方法,返回的是InputStream類。這樣所有的資源都被可以通過InputStream這個類來獲取,所以也屏蔽了資源的提供者。ResourceLoader接口屏蔽了所有的資源加載者的差異,只需要實現這個接口就可以加載所有的資源, 他的默認實現是DefaultResourceLoader。

  Context和Resource的關系:Context是把資源的加載、解析和描述工作委托給了ResourcePatternResolver類來完成,他相當於一個接頭人,他把資源的加載、解析和資源的定義整合在一起便於其他組件使用。

六、


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM