Spring入門03 - 依賴注入DI

入門 03 - 依賴注入DI
 IoC模式基本上是一個高層的概念,在Martin Fowler的Inversion of Control Containers and the Dependency Injection pattern中談到,實現IoC有兩種方式:Dependency Injection與Service Locator。您可以在下面的網址中找到該篇文章:
http://www.martinfowler.com/articles/injection.html<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
 Spring所採用的是Dependency Injection來實現IoC,中文翻譯爲依賴注入,依賴注入的意義是:「保留抽象接口,讓組件依賴於抽象接口,當組件要與其它實際的對象發生依賴關係時,藉過抽象接口來注入依賴的實際對象。」
 看看下面這個程序:

public class BusinessObject {

    private FloppyWriter writer = new FloppyWriter();

    ....

  

    public void save() {

        ...

        writer.saveToFloppy();

 

    }

}


 BusinessObject依賴於實際的FloppyWriter,爲了讓BusinessObject獲得重用性,我們不讓BusinessObject依賴於實際的FloppyWriter,而是依賴於抽象的接口:

public interface IDeviceWriter {

    public void saveToDevice();

}

 

public class BusinessObject {

    private IDeviceWriter writer;

 

    public void setDeviceWriter(IDeviceWriter writer) {

        this.writer = writer;

    }

 

    public void save() {

        ....

        writer.saveToDevice();

    }

}

 

public class FloppyWriter implement IDeviceWriter {

    public void saveToDevice() {

        ....

        // 實際儲存至Floppy的程序代碼

    }

}

 

public class UsbDiskWriter implement IDeviceWriter {

    public void saveToDevice() {

        ....

        // 實際儲存至UsbDisk的程序代碼

    }

}


 如果今天BusinessObject想要與UseDiskWriter對象發生依賴關係,可以這麼建立:

businessObject.setDeviceWriter(new UsbDiskWriter());


 由於BusinessObject依賴於抽象接口,在需要建立依賴關係時,我們可以透過抽象接口注入依賴的實際對象。
 依賴注入在Martin Fowler的文章中談到了三種實現方式:interface injection、setter injection與constructor injection。並分別稱其爲type 1 IoC、type 2 IoC與type 3 IoC。
 上面的BusinessObject所實現的是type 2 IoC,透過setter注入依賴關係,而type 3 IoC,則在是建構函式上注入依賴關係,例如:

public class BusinessObject {

    private IDeviceWriter writer;

 

    public BusinessObject(IDeviceWriter writer) {

        this.writer = writer;

    }

 

    public void save() {

        ....

        writer.saveToDevice();

    }

}


 Spring鼓勵的是setter injection,但也允許您使用constructor injection,使用setter或constructor來注入依賴關係視您的需求而定,使用constructor的好處之一是,您可以在建構物件的同時一併完成依賴關係的建立,然而如果要建立的對象關係很多,則會在建構函式上留下一長串的參數,這時使用setter會是個不錯的選擇,另一方面, setter可以有明確的名稱可以瞭解注入的對象會是什麼,像是setXXX()這樣的名稱會比記憶constructor上某個參數位置代表某個對象來得好。
 Type 1 IoC是interface injection,使用type 1 IoC時會要求實作接口,這個接口是爲容器所用的,容器知道接口上所規定的方法,它可以呼叫實作接口的對象來完成依賴關係的注入,例如:

public interface IDependencyInjection {

    public void createDependency(Map dependObjects);

}

 

public class BusinessObject implement IDependencyInjection {

    private Map dependObjects;

 

    public void createDependency(Map dependObjects) {

        this.dependObject = dependObjects;

        // 在這邊實現與BusinessObject的依賴關係

        ......

    }

 

    public void save() {

        ....

        writer.saveToDevice();

    }

}


 如果要完成依賴關係注入的對象,必須實現IDependencyInjection接口,並交由容器管理,容器會呼叫被管理對象的createDependency()方法來完成依賴關係的建立。
 在上面的例子中,type 1 IoC要求BusinessObject實現特定的接口,這就使得BusinessObject依賴於容器,如果日後BusinessObject要脫離目前這個容器,就必須修改程序,想想在更復雜的依賴關係中產生更多複雜的接口,組件與容器(框架)的依賴會更加複雜,最後使得組件無法從容器中脫離。
 所以type 1 IoC具有強的侵入性,使用它來實現依賴注入會使得組件相依於容器(框架),降低組件的重用性。

 Spring的核心是個IoC容器,您可以用setter或constructor的方式來實現您的業務對象,至於對象與對象之間的關係建立,則透過組態設定,讓Spring在執行時期根據組態檔的設定來爲您建立對象之間的依賴關係,您不必特地撰寫一些Helper來自行建立這些對象之間的依賴關係,這 不僅減少了大量的程序撰寫,也降低了對象之間的耦合程度。

發佈了106 篇原創文章 · 獲贊 0 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章