Spring系列三:IoC 與 DI

水晶簾動微風起,滿架薔薇一院香。java

https://user-gold-cdn.xitu.io/2019/10/18/16ddd77b37856c70?w=1920&h=1280&f=jpeg&s=338726
https://user-gold-cdn.xitu.io/2019/10/18/16ddd77b37856c70?w=1920&h=1280&f=jpeg&s=338726

概述

在軟件工程中,控制反轉(IoC)是一種設計思想,對象之間耦合在一塊兒,在運行時自動綁定,而且它們編譯時對所須要引用的對象是不肯定的。在這個spring教程中,經過示例瞭解iocspring中的依賴注入之間的區別。面試

什麼是控制反轉(IOC)

在傳統面向對象設計的軟件系統中,它的底層由N多個對象構成,各個對象之間經過相互合做。最終實現業務流程。控制反轉意指把建立和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,因此對象與對象之間是鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活,儘管有些人認爲使用服務定位器模式也能夠提供控制反轉。spring

使用控制反轉做爲設計準則有如下優勢:編程

  1. 某個任務的執行與實現是分離的
  2. 每一個模塊更關注與本身的設計。
  3. 模塊不須要關注其它系統,只須要依賴便可。
  4. 模塊的升級不會影響其它模塊

什麼是依賴注入(DI)

IoC是一種設計範例,其目標是對應用程序的各個組件提供更多控制,使這些組件能夠完成工做。依賴注入是一種模式,用於建立對象依賴的對象實例,且在編譯時期是無感知的。IoC依賴於依賴注入,由於它須要一種機制來建立且引用須要的組件。設計模式

這兩個概念以這種方式協同工做,容許編寫更靈活、可重用和封裝的代碼。所以,它們是設計面向對象解決方案的重要概念。微信

如何實現IoC

在面向對象的編程中,有幾種基本技術能夠實現控制反轉。以下:框架

  1. 使用工廠模式
  2. 使用服務定位器模式
  3. 使用如下任何給定類型的依賴項注入
  • 構造函數注入
  • setter注入
  • 註解注入

Spring中的控制反轉

org.springframework.beansorg.springframework.context包爲Spring框架的IoC容器提供了基礎功能。BeanFactory接口提供了更高級的配置項,可以管理全部對象。ApplicationContext接口創建在BeanFactory之上(它是一個子接口),並添加了其餘功能,例如與SpringAOP功能的更輕鬆集成,消息資源處理(用於國際化),事件傳播以及特定於應用程序層的上下文,例如做爲Web應用程序中使用的WebApplicationContext異步

BeanFactorySpring IoC容器的主要實現,負責包含和管理上述BeanBeanFactory接口是Spring中的重要的IoC容器接口。函數

https://user-gold-cdn.xitu.io/2019/10/18/16ddd7806eae992a?w=498&h=296&f=png&s=5950
https://user-gold-cdn.xitu.io/2019/10/18/16ddd7806eae992a?w=498&h=296&f=png&s=5950

BeanFactory接口有許多實現。最經常使用的BeanFactory實現是XmlBeanFactory類。其餘經常使用的類是XmlWebApplicationContext。根據bean的定義,工廠將返回所包含對象的不一樣實例(Prototype設計模式),或者返回單個共享實例(Singleton設計模式,其中實例是做用域中的單例)。的工廠)。將返回哪一種類型的實例取決於bean工廠的配置:獲取bean實例的API是相同的。學習

在深刻研究依賴注入類型以前,首先肯定在spring框架中建立bean的方式,由於它將有助於理解下一部分的內容。

如何在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但願可以調用此方法並返回一個可用的對象,獲得對象以後,該對象將被視爲是經過構造函數建立的。

使用實例工廠方法

以相似於經過靜態工廠方法進行實例化的方式,使用實例工廠方法進行實例化是調用容器中現有beanfactory方法來建立新bean

<bean id="myFactoryBean"  class="cn.howtodoinjava.MyFactoryBean">

<bean id="exampleBean"  factory-bean="myFactoryBean" factory-method="createInstance"></bean>
複製代碼

Spring的依賴注入

依賴項注入(DI)背後的基本原則是,對象僅經過構造函數參數、工廠方法的參數或屬性來定義它們的依賴項,這些參數是在對象實例被構造或從工廠方法返回後在對象實例上配置的。而後,容器的工做是在建立bean時實際注入這些依賴項。即由IoC容器幫對象找相應的依賴對象並注入,而不是由對象主動去找,所以稱爲控制反轉(IoC)。

setter 注入

經過調用無參數構造函數或無參數靜態工廠方法以實例化bean以後,在bean上調用setter方法,能夠實現基於setterDI

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;
  }
}
複製代碼

spring面試題

組件和服務之間有什麼區別?

組件是一組軟件,這些組件將被其它應用程序所使用,且不會進行任何更改。所謂「不更改」是指使用應用程序不會更改組件的源代碼,儘管它們能夠經過組件做者容許的方式擴展組件來更改組件的行爲。

服務與組件類似,供外部應用程序使用。主要的區別在於本地使用的組件(好比jar文件、程序集、dll或源導入)。服務將經過同步或異步的某個遠程接口(例如,Web服務,消息系統,RPC或套接字)遠程使用。

DI與服務定位器模式有何不一樣?

依賴項注入器的主要好處是,它容許根據環境和使用狀況注入合適的服務實現。注入不是打破這種依賴性的惟一方法,另外一種方法是使用服務定位器。服務定位器的基本思想是擁有一個對象,該對象知道如何掌握應用程序可能須要的全部服務。而後,它將掃描全部此類服務,並將它們存儲爲單例註冊表中。當要求提供服務實現時,請求者可使用令牌查詢註冊表並獲取適當的實現。

一般,這些註冊表是經過一些配置文件填充的。關鍵區別在於,使用服務定位器時,服務的每一個用戶都對定位器具備依賴性。定位器能夠隱藏對其餘實現的依賴關係,可是仍是須要查看定位器。

使用哪一個更好的服務(即服務定位器或依賴項注入)?

正如上文已經說過的,關鍵區別在於,使用服務定位器,服務的每一個用戶都對定位器有依賴性。這意味着必須在輸入和輸出方面瞭解服務定位器的詳細信息。所以,實際上成爲選擇哪一種模式的決定因素。

若是維護註冊表信息既簡單又必要,則可使用服務定位器,或者直接使用依賴注入,由於它對服務的使用者是無感知的

構造函數注入或setter或註解注入哪一個更好?

基於constructor的注入,會固定依賴注入的順序;該方式不容許咱們建立bean對象之間的循環依賴關係,這種限制實際上是一種利用構造器來注入的益處 - 當你甚至沒有注意到使用setter注入的時候,Spring能解決循環依賴的問題;

基於setter的注入,只有當對象是須要被注入的時候它纔會幫助咱們注入依賴,而不是在初始化的時候就注入;另外一方面若是你使用基於constructor注入,CGLIB不能建立一個代理,迫使你使用基於接口的代理或虛擬的無參數構造函數。

個人偏好是註解注入,這種方式看起來很是好,精短,可讀性高,不須要多餘的代碼,也方便維護;

什麼是BeanFactory ?

BeanFactory就像一個工廠類,其中包含一系列beanBeanFactory在其內部保存多個BeanBean定義,而後在客戶要求時實例化Bean

BeanFactory可以在實例化協做對象之間建立關聯。這消除了bean自己和bean客戶端的配置負擔。BeanFactory還參與bean的生命週期,從而調用自定義初始化和銷燬​​方法。

什麼是ApplicationContext ?

Bean工廠適合簡單的應用程序,可是要利用Spring框架的所有功能,您可能須要升級到Spring更高級的容器即應用程序上下文。從表面上看,應用程序上下文與Bean工廠相同,二者都加載Bean定義,將Bean綁定在一塊兒並根據請求分配Bean。但它也提供以下功能:

  • 解決文本消息的方法,包括對國際化的支持。
  • 加載文件資源的通用方法。
  • bean註冊監聽器的事件。

ApplicationContext的常見的實現有哪些 ?

ApplicationContext的三種經常使用實現是:

  1. ClassPathXmlApplicationContext:它從位於類路徑中的XML文件中加載上下文定義,並將上下文定義視爲類路徑資源。使用代碼從應用程序的類路徑中加載應用程序上下文。
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    
    複製代碼
  2. FileSystemXmlApplicationContext:它從文件系統中的XML文件加載上下文定義。使用代碼從文件系統中加載應用程序上下文。
ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
複製代碼
  1. XmlWebApplicationContext:它從Web應用程序中包含的XML文件中加載上下文定義。

BeanFactory或ApplicationContext最好使用哪一個 ?

BeanFactory基本上只是實例化和配置BeanApplicationContext也能夠作到這一點,它提供了支持基礎設施來支持許多企業特有的特性,例如事務和AOP

所以,建議使用ApplicationContext

在本教程中,咱們在spring學習了iocdi之間的區別。


https://user-gold-cdn.xitu.io/2019/10/14/16dc81e2dd98c311?w=258&h=258&f=jpeg&s=26702
https://user-gold-cdn.xitu.io/2019/10/14/16dc81e2dd98c311?w=258&h=258&f=jpeg&s=26702

🙂🙂🙂關注微信公衆號java乾貨 不按期分享乾貨資料

原文連接:Spring – IoC Containers

相關文章
相關標籤/搜索