控制反轉(Inversion of Control,英文縮寫為IoC)是框架的重要特徵,並非物件導向程式設計的專用術語。它與依賴注入(Dependency Injection,簡稱DI)和依賴查找(Dependency Lookup)並沒有關係。
一 .IOC的概念 : IOC (Inversion of Control) 即控制反轉,首先我們要搞清楚什麼被反轉了。 java程式中的業務邏輯大都需要多個物件來協作完成,通常,每個物件在使用他的合作物件時,自己都必須使用像new object() 這樣的語法來完成合作物件的申請工作。這樣一來物件間的耦合度就高了。而IOC的想法是:Spring容器來實現這些相互依賴物件的創建、協調工作。物件只需要關心業務邏輯本身就可以了。從這方面來說,物件如何得到他的協作物件的責任被反轉了。其實,IOC有個比較適合的名字叫做DI (Dependency Injection),也就是依賴注入。
舉個通俗的例子:假設現在有一個企業,企業需要有員工來完成相應的工作,那麼企業就需要自己想方設法的根據需求尋找這方面的的人才來為公司工作。這是一種傳統的方式,假設我們現在有了招聘網站,所有的人才都在網站上註冊自己的信息,寫明自己所擁有的技能和擅長的領域,當某個企業需要人才的時候,招聘網站就將特定的人才提供給公司,這樣企業就只需要發布用人需求就可以了。這個範例中的企業可以認為是業務類別EnterpriseService,人才是業務類別完成工作所需的協助類別Employee。那麼招募網站就相當於IOC容器
<code class="java"><span class="hljs-number"><span style="color: #000000"><br/>1 . 传统获取对象的方式<br/></span></span></code>
public class EnterpriseService { Employee employee = new Employee();//自己通过new Object()方式获取对象public void service() { employee.doSomething(); } }
<code class="java"><span class="hljs-number"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-title"><span class="hljs-keyword"><span class="hljs-comment"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-keyword"><span class="hljs-title"><span class="hljs-params"><span class="hljs-number">2 . 使用IOC容器方式<br/></span></span></span></span></span></span></span></span></span></span></span></span></span></code>
public class EnterpriseService { @Autowired Employee employee;//由容器完成对象的获取以及后续生命周期的管理public void service() { employee.doSomething(); } }
二 . DI 的原理分析
DI的原理很簡單,就是基於java的反射機制實現的。我們在使用spring的時候都會有一個xml設定文件,這個文件用來描述Bean與Bean之間的依賴關係。 IOC容器就是根據這個檔案來維護管理所有的Bean,並提供Bean實例緩存,生命週期管理,Bean實例代理,事件發布,資源裝載等高級任務。
IOC在啟動的時候會透過Resource和ResourceLoader協助完成資源檔案的讀取和解析,並將檔案中Bean的設定資訊儲存起來,然後在實例化該Bean的時候根據對應的類別載入器,透過反射呼叫Bean的setter方法,為實例注入在設定檔中配置的屬性來完成物件的建立。
三. 相關內容
1 . 從注入方法來看,有三種注入方式:建構子注入,屬性注入,介面注入 。 spring支援建構函式註入和屬性注入。
2 . BeanFactory是一個類別工廠,它是spring框架最核心的介面,它提供了高階IOC的設定機制, BeanFactory使管理不同類型的java物件成為可能,ApplicationContext建立在BeanFactory基礎之上,提供了更多應用程式導向的功能,例如國際化支援和框架時事件體系。
3 . 透過BeanFactory啟動IOC容器的時候並不會立即初始化設定檔中定義的Bean,初始化動作發生在第一次呼叫時。對於單例的Bean來說,BeanFactory會快取Bean的實例(基於HashMap實 現),所以再次呼叫getBeans方法的時候會直接從IOC容器的快取中取得Bean實例。
4 . ApplicationContext的主要實作類別是ClassPathXmlApplication和 FileSystemXmlApplicationContext.而WebApplicationContext繼承了ApplicationContext,是專門為web應用準備的,它允許從相對於web應用根目錄的路徑中尋找和加載設定檔(使用Resource介面和ResourceLoader<策略模式>介面實作)。 WebApplicationContext中可以取得ServletContext引用,整個 WebApplicationContext將作為屬性放置到ServletContext中,以便web應用環境可以存取 spring應用程式上下文。 web應用中增加了三個bean的作用域:request,session,global session 。 WebApplicationContext的初始化方式和BeanFactory和ApplicationContext有所區別,因為它需要ServletContext實例,也就是它必須在擁有web容器的前提下才能完成啟動工作#。
5 .ApplicationContext的初始化和BeanFactory的初始化一個重大的差異是: ApplicationContext在初始化應用程式上下文的時候就實例化所有的Bean。 另一個重大差異是:ApplicationContext會利用java反射機制自動辨識出設定檔中定義的BeanPostProcessor,InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,並自動將他們註冊到應用程式上下文中,而BeanFactory需要在程式碼中手動通過addBeanPostProcessor()方法進行註冊。
6 .對於scope="singleton"的Bean,spring會將bean放入IOC容器中緩存起來,將bean的引用返 回給調用者,並且繼續對這些bean進行後續的生命管理。每次呼叫getBeans方法回傳的是同一個bean,而對於scope="prototype"的Bean,spring將bean回傳給呼叫者後不再負責bean的生命 管,每次呼叫getBeans方法都會傳回一個新的bean。
以上是IOC的概念與分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!