IOC与依赖注入模式

1.IOC及注入模式简介
    为什么要用IOC,参见《为什么要用IOC
    IOC并不能清晰地解释类与类之间依赖的解耦关系,软件界的泰斗级人物Martin Fowler提出了DI(依赖注入:Dependency Injection)的概念,即将客户类对接口实现类的依赖关系由第三方(容器或协作类)注入,以移除客户类对具体接口实现类的依赖。
    我们使用抽象接口来隔离使用者和具体实现之间的依赖关系,但是不管再怎么抽象,最终还是要创建具体实现类的实例,这种创建具体实现类的实例对象就会造成对于具体实现的依赖,为了消除这种创建依赖性,需要把依赖移出到程序的外部(比如配置文件)。
    使用依赖注入后,这些类完全是基于抽象接口编写而成的,所以可以最大限度地适应需求的变化。依赖注入的形式有三种,分别为构造子注入(Constructor Injection)、设值方法注入(Setter Injection)和接口注入(Interface Injection)。

2.举例说明
现有一个服务接口,只有一个行为,
   Interface IService{
      go();
   }
Service类是接口IService的实现者
   public Service implements IService{
      public void go() {
         ...
      }
   }

Consumer类想调用这个服务,最原始的方法:
   public Consumer{
      private IService service = null;

      public Consumer(){
         service=new Service ();
      }

      public void doSomething() {
         service.go();
      }
   }

3.构造子注入
通过构造函数,将接口的具体实现类注入进来。代码如下
    public Consumer{
      private IService service = null;

      public Consumer(IService service){
         this.service=service
      }

      public void doSomething() {
         service.go();
      }
    }
调用过程如下
    Service service=new Service();
    Consumer consumer=new Consumer(service);
    consumer.doSomething();

4.Setter方法注入
    public Consumer{
      private IService service = null;

      public SetService(IService service){
         this.service=service
      }

      public void doSomething() {
         service.go();
      }
    }
调用过程如下
    Service service=new Service();
    Consumer consumer=new Consumer();
    consumer.SetService(service);
    consumer.doSomething();

5.接口注入
接口注入是指将客户类所有注入的方法抽取到一个接口中,客户类通过实现这一接口提供注入的方法。为了采取接口注入的方式,需要声明一个额外的接口:
    public interface Injectable{
       void injectService(IService service);
    }
Consumer类通过继承Injectable接口注入
    public Consumer implements Injectable{
      private IService service = null;

      public injectService(IService service){
         this.service=service;
      }

      public void doSomething() {
         service.go();
      }
    }
调用过程如下:
    Service service=new Service();
    Consumer consumer=new Consumer();
    consumer.injectService(service);
    consumer.doSomething();

由于通过接口注入需要额外声明一个接口,增加了类的数目,而且它的效果和属性注入并无本质区别,因此我们不提倡这种方式。

6.类与类之间依赖的管理

   类与类之间的依赖关系实现了解耦,但是类的实例化和类与类之间的注入依然是存在的,只是这个工作被延后并且由另外的类来完成,我们把管理这些类的实例化和对类与类之间关系进行管理的模块称之为第三方容器。
    这种容器帮助我们完成类的初始化和装配工作,让我们从这些底层的实现类实例化,依赖关系的装配中脱离出来,专注于更有意思的业务代码的编写工作,那确实是挺惬意的事情。Spring就是这样一个容器,它通过配置文件描述类之间的依赖关系,下面是Spring配置文件的对以上实例进行配置的样式代码:

    <beans>
        <bean id="myservice" class="com.Service"></bean>
        <bean id="consumer" class="com.Consumer">
            <property name="service"><ref bean="myservice"/></property>
        </bean>
    </beans>

    通过new XmlBeanFactory(“beans.xml”)等方式即可启动容器,在容器启动时,Spring根据配置文件的描述信息,通过Java的反射机制自动实例化Bean并完成依赖关系的建立,从容器中即可返回准备就绪的Bean实例,以待后续的使用。

你可能感兴趣的:(spring,bean,配置管理,IOC,Go)