IoC 容器
Spring 容器是 Spring 框架的核心。容器將創建對象,把它們連接在一起,配置它們,並管理他們的整個生命週期從創建到銷燬。Spring 容器使用依賴注入(DI)來管理組成一個應用程序的組件。這些對象被稱爲 Spring Beans,我們將在下一章中進行討論。
通過閱讀配置元數據提供的指令,容器知道對哪些對象進行實例化,配置和組裝。配置元數據可以通過 XML,Java 註釋或 Java 代碼來表示。下圖是 Spring 如何工作的高級視圖。 Spring IoC 容器利用 Java 的 POJO 類和配置元數據來生成完全配置和可執行的系統或應用程序。
IOC 容器具有依賴注入功能的容器,它可以創建對象,IOC 容器負責實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。通常new一個實例,控制權由程序員控制,而"控制反轉"是指new實例工作不由程序員來做而是交給Spring容器來做。在Spring中BeanFactory是IOC容器的實際代表者。
Spring 提供了以下兩種不同類型的容器。
IoC 全稱爲 如何理解“控制反轉”好呢?理解好它的關鍵在於我們需要回答如下四個問題:
在回答這四個問題之前,我們先看 IOC 的定義:
上面這句話是整個 IoC 理論的核心。如何來理解這句話?我們引用一個例子來走闡述(看完該例子上面四個問題也就不是問題了)。 已找女朋友爲例(對於程序猿來說這個值得探究的問題)。一般情況下我們是如何來找女朋友的呢?首先我們需要根據自己的需求(漂亮、身材好、性格好)找一個妹子,然後到處打聽她的興趣愛好、微信、電話號碼,然後各種投其所好送其所要,最後追到手。如下:
這就是我們通常做事的方式,如果我們需要某個對象,一般都是採用這種直接創建的方式( 其實我們需要思考一個問題?我們每次用到自己依賴的對象真的需要自己去創建嗎?我們知道,我們依賴對象其實並不是依賴該對象本身,而是依賴它所提供的服務,只要在我們需要它的時候,它能夠及時提供服務即可,至於它是我們主動去創建的還是別人送給我們的,其實並不是那麼重要。再說了,相比於自己千辛萬苦去創建它還要管理、善後而言,直接有人送過來是不是顯得更加好呢? 這個給我們送東西的“人” 就是 IoC,在上面的例子中,它就相當於一個婚介公司,作爲一個婚介公司它管理着很多男男女女的資料,當我們需要一個女朋友的時候,直接跟婚介公司提出我們的需求,婚介公司則會根據我們的需求提供一個妹子給我們,我們只需要負責談戀愛,生猴子就行了。你看,這樣是不是很簡單明瞭。 誠然,作爲婚介公司的 IoC 幫我們省略了找女朋友的繁雜過程,將原來的主動尋找變成了現在的被動接受(符合我們的要求),更加簡潔輕便。你想啊,原來你還得鞍馬前後,各種巴結,什麼東西都需要自己去親力親爲,現在好了,直接有人把現成的送過來,多麼美妙的事情啊。所以,簡單點說,IoC 的理念就是讓別人爲你服務,如下圖(摘自Spring揭祕): 在沒有引入 IoC 的時候,被注入的對象直接依賴於被依賴的對象,有了 IoC 後,兩者及其他們的關係都是通過 Ioc Service Provider 來統一管理維護的。被注入的對象需要什麼,直接跟 IoC Service Provider 打聲招呼,後者就會把相應的被依賴對象注入到被注入的對象中,從而達到 IOC Service Provider 爲被注入對象服務的目的。所以 IoC 就是這麼簡單!原來是需要什麼東西自己去拿,現在是需要什麼東西讓別人(IOC Service Provider)送過來 現在在看上面那四個問題,答案就顯得非常明顯了:
妹子有了,但是如何擁有妹子呢?這也是一門學問。
所以,IOC Service Provider 爲被注入對象提供被依賴對象也有如下幾種方式:構造方法注入、stter方法注入、接口注入。 構造器注入 構造器注入,顧名思義就是被注入的對象通過在其構造方法中聲明依賴對象的參數列表,讓外部知道它需要哪些依賴對象。
構造器注入方式比較直觀,對象構造完畢後就可以直接使用,這就好比你出生你家裏就給你指定了你媳婦。 setter 方法注入 對於 JavaBean 對象而言,我們一般都是通過 getter 和 setter 方法來訪問和設置對象的屬性。所以,當前對象只需要爲其所依賴的對象提供相對應的 setter 方法,就可以通過該方法將相應的依賴對象設置到被注入對象中。如下:
相比於構造器注入,setter 方式注入會顯得比較寬鬆靈活些,它可以在任何時候進行注入(當然是在使用依賴對象之前),這就好比你可以先把自己想要的妹子想好了,然後再跟婚介公司打招呼,你可以要林志玲款式的,趙麗穎款式的,甚至鳳姐哪款的,隨意性較強。 接口方式注入 接口方式注入顯得比較霸道,因爲它需要被依賴的對象實現不必要的接口,帶有侵入性。一般都不推薦這種方式。 關於 IOC 理論部分,筆者不在闡述,這裏推薦幾篇博客閱讀:
各個組件先看下圖(摘自:http://singleant.iteye.com/blog/1177358) 該圖爲 ClassPathXmlApplicationContext 的類繼承體系結構,雖然只有一部分,但是它基本上包含了 IOC 體系中大部分的核心類和接口。 下面我們就針對這個圖進行簡單的拆分和補充說明。 Resource體系 Resource,對資源的抽象,它的每一個實現類都代表了一種資源的訪問策略,如ClasspathResource 、 URLResource ,FileSystemResource 等。 有了資源,就應該有資源加載,Spring 利用 ResourceLoader 來進行統一資源加載,類圖如下: BeanFactory 體系 BeanFactory 是一個非常純粹的 bean 容器,它是 IOC 必備的數據結構,其中 BeanDefinition 是她的基本結構,它內部維護着一個 BeanDefinition map ,並可根據 BeanDefinition 的描述進行 bean 的創建和管理。 BeanFacoty 有三個直接子類 Beandefinition 體系 BeanDefinition 用來描述 Spring 中的 Bean 對象。 BeandefinitionReader體系 BeanDefinitionReader 的作用是讀取 Spring 的配置文件的內容,並將其轉換成 Ioc 容器內部的數據結構:BeanDefinition。 ApplicationContext體系 這個就是大名鼎鼎的 Spring 容器,它叫做應用上下文,與我們應用息息相關,她繼承 BeanFactory,所以它是 BeanFactory 的擴展升級版,如果BeanFactory 是屌絲的話,那麼 ApplicationContext 則是名副其實的高富帥。由於 ApplicationContext 的結構就決定了它與 BeanFactory 的不同,其主要區別有:
下圖來源:https://blog.csdn.net/yujin753/article/details/47043143 上面五個體系可以說是 Spring IoC 中最核心的部分,後面博文也是針對這五個部分進行源碼分析。其實 IoC 咋一看還是挺簡單的,無非就是將配置文件(暫且認爲是 xml 文件)進行解析(分析 xml 誰不會啊),然後放到一個 Map 裏面就差不多了,初看有道理,其實要面臨的問題還是有很多的 |
|
---|---|
ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常建議超過 BeanFactory。BeanFactory 仍然可以用於輕量級的應用程序,如移動設備或基於 applet 的應用程序,其中它的數據量和速度是顯著。