天天看點

spring中的依賴注入和控制反轉(一)

  控制反轉(Inversion of Control,英文縮寫為IoC)是一個重要的面向對象程式設計法則來削減計算機程式的耦合問題,也是輕量級的Spring架構的核心。控制反轉一般分為兩種類型,依賴注入(Dependency Injection,簡稱DI)和依賴查找(DependencyLookup)。依賴注入應用比較廣泛。

  1.控制反轉(Inversion of Control)與依賴注入(Dependency Injection)

  控制反轉,它把傳統上由程式代碼直接操控的對象的調用權交給容器,通過容器來實作對象元件的裝配和管理。所謂的“控制反轉”概念就是對元件對象控制權的轉移,從程式代碼本身轉移到了外部容器。

  IoC是一個很大的概念,可以用不同的方式來實作。其主要實作方式有兩種:<1>依賴查找(Dependency Lookup):容器提供回調接口和上下文環境給元件。EJB和Apache Avalon都使用這種方式。<2>依賴注入(DependencyInjection):元件不做定位查詢,隻提供普通的Java方法讓容器去決定依賴關系。後者是時下最流行的IoC類型,其又有接口注入(Interface Injection),設值注入(Setter Injection)和構造子注入(ConstructorInjection)三種方式。

  依賴注入之是以更流行是因為它是一種更可取的方式:讓容器全權負責依賴查詢,受管元件隻需要暴露JavaBean的setter方法或者帶參數的構造子或者接口,使容器可以在初始化時組裝對象的依賴關系。其與依賴查找方式相比,主要優勢為:<1>查找定位操作與應用代碼完全無關。<2>不依賴于容器的API,可以很容易地在任何容器以外使用應用對象。<3>不需要特殊的接口,絕大多數對象可以做到完全不必依賴容器

  2.spring中的控制反轉和依賴注入

  在spring中,不管是依賴注入,還是控制反轉,他們的含義是完全相同的。當某個java對象需要調用另一個java對象的方法是,在傳統模式下通常有如下做法:

  原始做法:調用者主動建立被依賴對象,然後再調用被依賴對象的方法

  簡單工廠模式:調用者先找到被依賴對象的工程,然後主動通過工廠去擷取被依賴對象,最後在調用被依賴對象的方法。

   對于原始做法,由于調用者需要通過形如“new被依賴對象的構造器();”的代碼建立對象,是以必然導緻調用者與依賴對象實作類的寫死耦合,非常不利于項目更新和維護。

  對于簡單工廠來說,大緻需要把握三點:第一,調用者面向被依賴對象的接口變成;第二,将被依賴對象建立交個工廠完成;第三,調用者通過工廠來獲得被依賴的元件。通過這三點改造,可以保證調用者隻需與被依賴對象的接口耦合,這就避免了類層次的寫死耦合。這種方式衛衣的缺點是,調用元件需要主動通過工程去擷取被依賴對象,這就會帶來調用元件與被依賴對象工程的耦合。

  使用spring架構之後,調用者無需主動擷取被依賴對象,調用者隻要被動接收spring容器為調用者的成員變量指派即可(隻要配置一個<property ../>子元素,spring就會執行對應的setter方法為調用者的成員變量指派 )。由此可見,使用spring架構之後,調用者擷取被依賴對象的方式由原來的主動擷取變成了被動接受,于是——Rod Johnson将這種方式成為控制反轉

  從spring容器的角度來看,spring容器負責将被依賴對象指派給調用者的成員變量——相當于調用者 注入它的依賴的執行個體,是以Martine Fowler 将這種方式成為依賴注入。

  正因為spring将被依賴對象注入給調用者,是以調用者無需主動擷取被依賴對象,隻要被動等待spring容器注入即可,由此可見,控制反轉和依賴注入其實是同一種行為的兩種表達,隻是描述角度不同而已。

  3.依賴注入類型

  依賴注入主要通過設值注入和構造注入兩種。

      設值注入是指IOC容器通過成員變量的setter方法來注入被依賴對象。這種注入方式簡單、直覺,因為在spring的依賴注入裡面大量使用;

      構造注入是在構造執行個體時,已經完成了依賴關系的初始化。通俗來說,就是驅動spring在底層一反射方式執行帶指定參數的構造器,當執行帶參數的構造器是,就可以來用構造器參數對成員變量執行初始化——這就是構造注入的本質。