Spring核心元件詳解(Bean、Context、Core)
上篇文章介紹了Spring的有三個核心元件,它們為什麼是Spring的核心元件,它們之間啥關係,都代表了啥角色。
下面將詳細介紹每個元件內部類的層次關係,以及它們在執行時的時序順序。我們在使用 Spring 是應該注意的地方。
核心元件詳解
Bean 元件
前面已經說明了 Bean 元件對 Spring 的重要性,下面看看 Bean 這個元件式怎麼設計的。Bean 元件在 Spring 的 org.springframework.beans 包下。這個包下的所有類主要解決了三件事:Bean 的定義、Bean 的建立以及對 Bean 的解析。對 Spring 的使用者來說唯一需要關心的就是 Bean 的建立
Spring Bean 的建立時典型的工廠模式,他的頂級介面是 BeanFactory,下圖是這個工廠的繼承層次關係:
圖 4. Bean 工廠的繼承關係
BeanFactory 有三個子類:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。但是從上圖中我們可以發現最終的預設實現類是 DefaultListableBeanFactory,他實現了所有的介面。那為何要定義這麼多層次的介面呢?查閱這些介面的原始碼和說明發現,每個介面都有他使用的場合,它主要是為了區分在 Spring 內部在操作過程中物件的傳遞和轉化過程中,對物件的資料訪問所做的限制。例如 ListableBeanFactory 介面表示這些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是這些 Bean 是有繼承關係的,也就是每個 Bean 有可能有父 Bean。AutowireCapableBeanFactory 介面定義 Bean 的自動裝配規則。這四個介面共同定義了 Bean 的集合、Bean 之間的關係、以及 Bean 行為。
Bean 的定義主要有 BeanDefinition 描述,如下圖說明了這些類的層次關係:
圖 5. Bean 定義的類層次關係圖
Bean 的定義就是完整的描述了在 Spring 的配置檔案中你定義的 <bean/> 節點中所有的資訊,包括各種子節點。當 Spring 成功解析你定義的一個 <bean/> 節點後,在 Spring 的內部他就被轉化成 BeanDefinition 物件。以後所有的操作都是對這個物件完成的。
Bean 的解析過程非常複雜,功能被分的很細,因為這裡需要被擴充套件的地方很多,必須保證有足夠的靈活性,以應對可能的變化。Bean 的解析主要就是對 Spring 配置檔案的解析。這個解析過程主要通過下圖中的類完成:
圖 6. Bean 的解析類
當然還有具體對 tag 的解析這裡並沒有列出。
Context 元件
Context 在 Spring 的 org.springframework.context 包下,前面已經講解了 Context 元件在 Spring 中的作用,他實際上就是給 Spring 提供一個執行時的環境,用以儲存各個物件的狀態。下面看一下這個環境是如何構建的。
ApplicationContext 是 Context 的頂級父類,他除了能標識一個應用環境的基本資訊外,他還繼承了五個介面,這五個介面主要是擴充套件了 Context 的功能。下面是 Context 的類結構圖:
圖 7. Context 相關的類結構圖
從上圖中可以看出 ApplicationContext 繼承了 BeanFactory,這也說明了 Spring 容器中執行的主體物件是 Bean,另外 ApplicationContext 繼承了 ResourceLoader 介面,使得 ApplicationContext 可以訪問到任何外部資源,這將在 Core 中詳細說明。
ApplicationContext 的子類主要包含兩個方面:
- ConfigurableApplicationContext 表示該 Context 是可修改的,也就是在構建 Context 中使用者可以動態新增或修改已有的配置資訊,它下面又有多個子類,其中最經常使用的是可更新的 Context,即 AbstractRefreshableApplicationContext 類。
- WebApplicationContext 顧名思義,就是為 web 準備的 Context 他可以直接訪問到 ServletContext,通常情況下,這個介面使用的少。
再往下分就是按照構建 Context 的檔案型別,接著就是訪問 Context 的方式。這樣一級一級構成了完整的 Context 等級層次。
總體來說 ApplicationContext 必須要完成以下幾件事:
- 標識一個應用環境
- 利用 BeanFactory 建立 Bean 物件
- 儲存物件關係表
- 能夠捕獲各種事件
Context 作為 Spring 的 Ioc 容器,基本上整合了 Spring 的大部分功能,或者說是大部分功能的基礎。
Core 元件
Core 元件作為 Spring 的核心元件,他其中包含了很多的關鍵類,其中一個重要組成部分就是定義了資源的訪問方式。這種把所有資源都抽象成一個介面的方式很值得在以後的設計中拿來學習。下面就重要看一下這個部分在 Spring 的作用。
下圖是 Resource 相關的類結構圖:
圖 8. Resource 相關的類結構圖
從上圖可以看出 Resource 介面封裝了各種可能的資源型別,也就是對使用者來說遮蔽了檔案型別的不同。對資源的提供者來說,如何把資源包裝起來交給其他人用這也是一個問題,我們看到 Resource 介面繼承了 InputStreamSource 介面,這個介面中有個 getInputStream 方法,返回的是 InputStream 類。這樣所有的資源都被可以通過 InputStream 這個類來獲取,所以也遮蔽了資源的提供者。另外還有一個問題就是載入資源的問題,也就是資源的載入者要統一,從上圖中可以看出這個任務是由 ResourceLoader 介面完成,他遮蔽了所有的資源載入者的差異,只需要實現這個介面就可以載入所有的資源,他的預設實現是 DefaultResourceLoader。
下面看一下 Context 和 Resource 是如何建立關係的?首先看一下他們的類關係圖:
圖 9. Context 和 Resource 的類關係圖
從上圖可以看出,Context 是把資源的載入、解析和描述工作委託給了 ResourcePatternResolver 類來完成,他相當於一個接頭人,他把資源的載入、解析和資源的定義整合在一起便於其他元件使用。Core 元件中還有很多類似的方式。