zoukankan      html  css  js  c++  java
  • 依赖注入

    作为一条设计原则,依赖倒置原则(DIP)强调高层组件应该依赖于抽象而不是某个具体的实现或功能。控制反转(IoC)就是对依赖倒置原则的一个应用,用一段泛化的代码控制更加特定的外部组件的执行。

    在一个控制反转解决方案中,方法通常会有一个或多个空缺点。每个空缺点的功能都由外部组件提供(静态的或者动态的),并通过 抽象接口调用。若满足了里氏替换原则和开放/封闭原则,那么改变任何外部组件都不会影响高层次的方法。外部组件和高层次方法可以分开开发。

    控制反转的一个现实实例是Windows的shell扩展。当用户右键单击并选择“属性”命令时,Windows资源管理器会准备一个标准的对话框,随后执行一系列的控制反转。Windows将查看注册表,判断是否有已经注册过的自定义的属性页。若存在,Windows将通过一系列接口与这些扩展通信,并将页面添加至属性对话框中。

    控制反转的另一个实现实例是事件驱动编程,起源于Visual Basic,现在已得到了Windows Form和Web Form的支持。例如,若编写了一个Button1_Click方法,并将其关联到Button1控件的Click事件上,那么也就是让Button类的代码(可重用且足够泛化)在用户单击时回调Button1_Click方法。

    那么依赖注入(Dependency Injection,DI)又是什么呢?

    从依赖倒置到依赖注入

    在这里的讨论中,控制反转和依赖注入可以认为是同义词。不过在字面上二者并不总是同义词,控制反转有时会指导原则,而依赖注入则表明了原则的应用——即模式。实际上,控制反转历史上曾是基于依赖倒置原则的一个模式。依赖注入这个名词有Martin Fowler提出,用来专指控制反转的概念。

    控制反转/依赖注入作为一个模式,可以让高层次方法不再需要辅助组件的具体引用。注入的过程可以通过三种方式来实现,一种是通过被注入方法所在的类的构造函数;第二种是通过在被注入方法所在的类中定义一个方法或者属性;最后一种是让被注入方法所在的类实现一个接口,接口中提供了辅助组件的具体实现。

    目前,控制反转/依赖注入通常会随着某专门的框架提供,这些框架也提供了很多高级功能。

    IoC框架

    当前比较流行的几个Ioc框架。

    Castle Windsor http://www.castleproject.org/container/index.html

    Ninject http://www.ninject.org

    Spring.Net http://www.springframework.net

    StructureMap http://structuremap.sourceforge.net/Default.html

    Unity http://codeplex.com/Unity

    其中Ninject还可用于Silverlight和.NET Compact Framework。微软的Unity Application Block 是一个轻量级的IoC容器,支持构造函数、属性和方法的注入。Unity跟微软企业库一起发布。

    所有的IoC容器框架有基于一个容器对象构造,这个容器对象将和一些配置信息绑定,并解析依赖。调用者代码将实例化容器,并将需要的接口以参数的形式传入,作为响应,Ioc/DI框架将返回一个实现了该接口的具体对象。

    Ioc容器实战

    假设某个类依赖于一个日志服务:

    public class Task
        {
            private ILogger _logger;
            public Task(ILogger logger)
            {
                this._logger = logger;
            }
            public void Execute()
            {
                this._logger.Log("Begin method..");
    
                this._logger.Log("End method..");
            }
        }
    

    Task类将通过构造函数接收日志组件,不过Task事故如何定位并初始化这个组件的呢?使用的静态new语句自然没有问题,这就要用到工厂。而IoC容器则是一个功能更加强大的框架,支持配置信息。

    <configuration>
      <configSections>
        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
      </configSections>
    
      <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
        <alias alias="ILogger" type="MyApp.ILogger, MyApp" />
        <namespace name="MyApp.Implementations" />
        <assembly name="MyApp" />
        
        <container>
          <register type="ILogger" name="special" mapTo="DbLogger" />    
        </container>
      </unity>
    </configuration>
    

    配置文件(app.config或者web.config)中将包含接口和将要注入的具体类型之间的映射。当容器调用ILogger时,将会返回一个DbLogger类型实例。

        IUnityContainer container = new UnityContainer();
                UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
    
                section.Containers.Default.Configure(container);
                ILogger logger = container.Resolve<ILogger>();
                Task t = new Task(logger);
    

    对于测试而言,IoC/DI非常有用,因为它可以很容易地在不同的实现中切换。框架的使用让IoC/DI更加简单。通过脚本配置,可以让容器以单例的形式对待某个注入对象,这就意味着容器不会每次创建新的DbLogger实例,而是重用其唯一的实例。若DbLogger类是线程安全的话,那么的确能够大大提升效率。

    此外,若DbLogger的构造函数需要引用到IoC/DI框架中注册的另一个类型,那么容器也能顺利地解析到该依赖。

    Martin Fowler关于控制反转/依赖注入的论文

  • 相关阅读:
    Web Api跨域访问配置及调用示例
    EasyUI datagrid 日期时间格式化
    bootstrap-table组合表头
    Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web mod
    Java 开发环境配置
    一台电脑上配置多个tomcat
    使用plsql Developer 连接远程服务器
    阿里云初识
    算法入门———冒泡排序
    算法入门———递归
  • 原文地址:https://www.cnblogs.com/luoht/p/2558965.html
Copyright © 2011-2022 走看看