入门 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 
 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来自行建立这些对象之间的依赖关系,这 不仅减少了大量的程序撰写,也降低了对象之间的耦合程度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值