水晶簾動微風起,滿架薔薇一院香。java
在軟件工程中,控制反轉(IoC
)是一種設計思想,對象之間耦合在一塊兒,在運行時自動綁定,而且它們編譯時對所須要引用的對象是不肯定的。在這個spring
教程中,經過示例瞭解ioc
和spring
中的依賴注入之間的區別。面試
在傳統面向對象設計的軟件系統中,它的底層由N多個對象構成,各個對象之間經過相互合做。最終實現業務流程。控制反轉意指把建立和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,因此對象與對象之間是鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活,儘管有些人認爲使用服務定位器模式也能夠提供控制反轉。spring
使用控制反轉做爲設計準則有如下優勢:編程
IoC
是一種設計範例,其目標是對應用程序的各個組件提供更多控制,使這些組件能夠完成工做。依賴注入是一種模式,用於建立對象依賴的對象實例,且在編譯時期是無感知的。IoC
依賴於依賴注入,由於它須要一種機制來建立且引用須要的組件。設計模式
這兩個概念以這種方式協同工做,容許編寫更靈活、可重用和封裝的代碼。所以,它們是設計面向對象解決方案的重要概念。微信
在面向對象的編程中,有幾種基本技術能夠實現控制反轉。以下:框架
org.springframework.beans
和org.springframework.context
包爲Spring
框架的IoC
容器提供了基礎功能。BeanFactory
接口提供了更高級的配置項,可以管理全部對象。ApplicationContext
接口創建在BeanFactory
之上(它是一個子接口),並添加了其餘功能,例如與Spring
的AOP
功能的更輕鬆集成,消息資源處理(用於國際化),事件傳播以及特定於應用程序層的上下文,例如做爲Web
應用程序中使用的WebApplicationContext
異步
BeanFactory
是Spring IoC
容器的主要實現,負責包含和管理上述Bean
。BeanFactory
接口是Spring
中的重要的IoC
容器接口。函數
BeanFactory
接口有許多實現。最經常使用的BeanFactory
實現是XmlBeanFactory
類。其餘經常使用的類是XmlWebApplicationContext
。根據bean
的定義,工廠將返回所包含對象的不一樣實例(Prototype
設計模式),或者返回單個共享實例(Singleton
設計模式,其中實例是做用域中的單例)。的工廠)。將返回哪一種類型的實例取決於bean
工廠的配置:獲取bean
實例的API
是相同的。學習
在深刻研究依賴注入類型以前,首先肯定在spring
框架中建立bean
的方式,由於它將有助於理解下一部分的內容。
Bean
定義能夠看做是建立一個或多個實際對象的配置。獲取時,容器會查看命名bean
的配置,並使用該bean
定義封裝的配置項來建立(或獲取)實際對象。
當使用構造函數方法建立bean
時,全部普通類均可以被Spring
使用並與之兼容。也就是說,正在建立的類不須要實現任何特定的接口或以特定的方式進行編碼。僅指定bean
類就足夠了。使用基於XML
的配置項時,能夠像這樣指定bean
類:
<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean"/>
複製代碼
在定義要使用靜態工廠方法建立的bean
以及指定包含靜態工廠方法的類的class
屬性時,須要另外一個名爲factory-method
的屬性來指定工廠方法自己的名稱。
<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean" factory-method="createInstance"/>
複製代碼
Spring
但願可以調用此方法並返回一個可用的對象,獲得對象以後,該對象將被視爲是經過構造函數建立的。
以相似於經過靜態工廠方法進行實例化的方式,使用實例工廠方法進行實例化是調用容器中現有bean
的factory
方法來建立新bean
。
<bean id="myFactoryBean" class="cn.howtodoinjava.MyFactoryBean">
<bean id="exampleBean" factory-bean="myFactoryBean" factory-method="createInstance"></bean>
複製代碼
依賴項注入(DI
)背後的基本原則是,對象僅經過構造函數參數、工廠方法的參數或屬性來定義它們的依賴項,這些參數是在對象實例被構造或從工廠方法返回後在對象實例上配置的。而後,容器的工做是在建立bean時實際注入這些依賴項。即由IoC
容器幫對象找相應的依賴對象並注入,而不是由對象主動去找,所以稱爲控制反轉(IoC
)。
經過調用無參數構造函數或無參數靜態工廠方法以實例化bean
以後,在bean
上調用setter
方法,能夠實現基於setter
的DI
。
public class TestSetterDI {
DemoBean demoBean = null;
public void setDemoBean(DemoBean demoBean) {
this.demoBean = demoBean;
}
}
複製代碼
基於構造函數的DI
是經過調用具備多個參數(每一個參數表明一個對象實例)的構造函數來實現的。另外,調用帶有特定參數的靜態工廠方法來構造Bean
幾乎是等效的,本文的其他部分將相似地考慮構造函數的參數和靜態工廠方法的參數。
public class ConstructorDI {
DemoBean demoBean = null;
public TestSetterDI (DemoBean demoBean) {
this.demoBean = demoBean;
}
}
複製代碼
註解注入只須要在須要在成員變量上添加@Autowire
註解便可
public class ConstructorDI {
@Autowire
private DemoBean demoBean;
}
}
複製代碼
組件是一組軟件,這些組件將被其它應用程序所使用,且不會進行任何更改。所謂「不更改」是指使用應用程序不會更改組件的源代碼,儘管它們能夠經過組件做者容許的方式擴展組件來更改組件的行爲。
服務與組件類似,供外部應用程序使用。主要的區別在於本地使用的組件(好比jar
文件、程序集、dll
或源導入)。服務將經過同步或異步的某個遠程接口(例如,Web
服務,消息系統,RPC
或套接字)遠程使用。
依賴項注入器的主要好處是,它容許根據環境和使用狀況注入合適的服務實現。注入不是打破這種依賴性的惟一方法,另外一種方法是使用服務定位器。服務定位器的基本思想是擁有一個對象,該對象知道如何掌握應用程序可能須要的全部服務。而後,它將掃描全部此類服務,並將它們存儲爲單例註冊表中。當要求提供服務實現時,請求者可使用令牌查詢註冊表並獲取適當的實現。
一般,這些註冊表是經過一些配置文件填充的。關鍵區別在於,使用服務定位器時,服務的每一個用戶都對定位器具備依賴性。定位器能夠隱藏對其餘實現的依賴關係,可是仍是須要查看定位器。
正如上文已經說過的,關鍵區別在於,使用服務定位器,服務的每一個用戶都對定位器有依賴性。這意味着必須在輸入和輸出方面瞭解服務定位器的詳細信息。所以,實際上成爲選擇哪一種模式的決定因素。
若是維護註冊表信息既簡單又必要,則可使用服務定位器,或者直接使用依賴注入,由於它對服務的使用者是無感知的
基於constructor
的注入,會固定依賴注入的順序;該方式不容許咱們建立bean
對象之間的循環依賴關係,這種限制實際上是一種利用構造器來注入的益處 - 當你甚至沒有注意到使用setter
注入的時候,Spring
能解決循環依賴的問題;
基於setter
的注入,只有當對象是須要被注入的時候它纔會幫助咱們注入依賴,而不是在初始化的時候就注入;另外一方面若是你使用基於constructor
注入,CGLIB
不能建立一個代理,迫使你使用基於接口的代理或虛擬的無參數構造函數。
個人偏好是註解注入,這種方式看起來很是好,精短,可讀性高,不須要多餘的代碼,也方便維護;
BeanFactory
就像一個工廠類,其中包含一系列bean
。BeanFactory
在其內部保存多個Bean
的Bean
定義,而後在客戶要求時實例化Bean
。
BeanFactory
可以在實例化協做對象之間建立關聯。這消除了bean
自己和bean
客戶端的配置負擔。BeanFactory
還參與bean
的生命週期,從而調用自定義初始化和銷燬方法。
Bean
工廠適合簡單的應用程序,可是要利用Spring
框架的所有功能,您可能須要升級到Spring
更高級的容器即應用程序上下文。從表面上看,應用程序上下文與Bean
工廠相同,二者都加載Bean
定義,將Bean
綁定在一塊兒並根據請求分配Bean
。但它也提供以下功能:
bean
註冊監聽器的事件。ApplicationContext
的三種經常使用實現是:
ClassPathXmlApplicationContext
:它從位於類路徑中的XML
文件中加載上下文定義,並將上下文定義視爲類路徑資源。使用代碼從應用程序的類路徑中加載應用程序上下文。ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
複製代碼
FileSystemXmlApplicationContext
:它從文件系統中的XML
文件加載上下文定義。使用代碼從文件系統中加載應用程序上下文。ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
複製代碼
XmlWebApplicationContext
:它從Web
應用程序中包含的XML文件中加載上下文定義。BeanFactory
基本上只是實例化和配置Bean
。ApplicationContext
也能夠作到這一點,它提供了支持基礎設施來支持許多企業特有的特性,例如事務和AOP
。
所以,建議使用ApplicationContext
。
在本教程中,咱們在spring
學習了ioc
和di
之間的區別。
🙂🙂🙂關注微信公衆號java乾貨 不按期分享乾貨資料