zoukankan      html  css  js  c++  java
  • 控制反转(IoC)与依赖注入(DI)

    控制反转(IoC)与依赖注入(DI) 2009-01-14 22:57:47

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://zhangjunhd.blog.51cto.com/113473/126530
    1.控制反转(Inversion of Control)与依赖注入(Dependency Injection)
    控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交 给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
    IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:<1>依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都使用这种方式。<2>依赖注入(Dependency Injection): 组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入(Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。
    650) this.width=650;" .click="window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)" http:="" blog.51cto.com="" viewpic.php?refimg=" + this.src)" src="http://zhangjunhd.blog.51cto.com/attachment/200901/200901141231944972691.jpg" alt="" border="0">
    图1 控制反转概念结构
    依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子或者接 口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:<1>查找定位操作与应用代码完 全无关。<2>不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。<3>不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
     
    2.好莱坞原则
    IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。第一次遇到好莱坞原则是在了解模板方法(Template Mathod)模式的 时候,模板方法模式的核心是,基类(抽象类)定义了算法的骨架,而将一些步骤延迟到子类中。
    650) this.width=650;" .click="window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)" http:="" blog.51cto.com="" viewpic.php?refimg=" + this.src)" src="http://zhangjunhd.blog.51cto.com/attachment/200901/200901141231944986707.jpg" alt="" border="0">
    图2 模板方法模式类图
     
    现在来考虑IoC的实现机制,组件定义了整个流程框架,而其中的一些业务逻辑的实现要借助于其他业务对象的加入,它们 可以通过两种方式参与到业务流程中,一种是依赖查找(Dependency Lookup),类似与JDNI的实现,通过JNDI来找到相应的业务对象(代码1),另一种是依赖注入,通过IoC容器将业务对象注入到组件中。
     
    3. 依赖查找(Dependency Lookup
    下面代码展示了基于JNDI实现的依赖查找机制。
    public class MyBusniessObject{
      private DataSource ds;
      private MyCollaborator myCollaborator;
     
      public MyBusnissObject(){
    Context ctx = null;
    try{
        ctx = new InitialContext();
        ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);
        myCollaborator =
     (MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);
        }……
    代码1依赖查找(Dependency Lookup)代码实现
    依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代JNDI来查找资源和协作对象,就必须把JNDI代码抽出来重构到一个策略方法中 去。
     
    4. 依赖注入(Dependency Injection
    依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从 应用组件的代码中抽取出来,交给IoC容器负责。
    下面分别演示3中注入机制。
    代码2 待注入的业务对象Content.java
    package com.zj.ioc.di;
     
    public class Content {
     
        public void BusniessContent(){
           System.out.println("do business");
        }
       
        public void AnotherBusniessContent(){
           System.out.println("do another business");
        }
    }
    MyBusniess类展示了一个业务组件,它的实现需要对象Content的注入。代码3,代码4,代码5,6分别演示构造子注入(Constructor Injection),设值注入(Setter Injection)和接口注入(Interface Injection)三种方式。
     
    代码3构造子注入(Constructor Injection)MyBusiness.java
    package com.zj.ioc.di.ctor;
    import com.zj.ioc.di.Content;
     
    public class MyBusiness {
        private Content myContent;
     
        public MyBusiness(Content content) {
           myContent = content;
        }
       
        public void doBusiness(){
           myContent.BusniessContent();
        }
       
        public void doAnotherBusiness(){
           myContent.AnotherBusniessContent();
        }
    }
     
    代码4设值注入(Setter Injection) MyBusiness.java
    package com.zj.ioc.di.set;
    import com.zj.ioc.di.Content;
     
    public class MyBusiness {
        private Content myContent;
     
        public void setContent(Content content) {
           myContent = content;
        }
       
        public void doBusiness(){
           myContent.BusniessContent();
        }
       
        public void doAnotherBusiness(){
           myContent.AnotherBusniessContent();
        }
    }
     
    代码5 设置注入接口InContent.java
    package com.zj.ioc.di.iface;
    import com.zj.ioc.di.Content;
     
    public interface InContent {
        void createContent(Content content);
    }
     
    代码6接口注入(Interface Injection)MyBusiness.java
    package com.zj.ioc.di.iface;
    import com.zj.ioc.di.Content;
     
    public class MyBusiness implements InContent{
        private Content myContent;
     
        public void createContent(Content content) {
           myContent = content;
        }
       
        public void doBusniess(){
           myContent.BusniessContent();
        }
       
        public void doAnotherBusniess(){
           myContent.AnotherBusniessContent();
        }
    }
     
    5.依赖拖拽(Dependency Pull)
    最后需要介绍的是依赖拖拽,注入的对象如何与组件发生联系,这个过程就是通过依赖拖拽实现。
    代码7 依赖拖拽示例
    public static void main(String[] args) throws Exception{
    //get the bean factory
    BeanFactory factory = getBeanFactory();
    MessageRender mr = (MessageRender) factory.getBean(“renderer”);
    mr.render();
    }
    而通常对注入对象的配置可以通过一个xml文件完成。
    使用这种方式对对象进行集中管理,使用依赖拖拽与依赖查找本质的区别是,依赖查找是在业务组件代码中 进行的,而不是从一个集中的注册处,特定的地点执行。

    本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/126530

  • 相关阅读:
    redmine工作流程总结
    IOS_OC_Category
    权限问题导致无法删除ftp文件
    Window下UDP(socket)接和收数据案例
    新一批创业者入局 谁来挖掘其身上的金矿
    java代理使用 apache ant实现文件压缩/解压缩
    ZOJ Monthly, November 2012
    【cocos2d-x 3.7 飞机大战】 决战南海I (十) 游戏主场景
    getAttribute for IE7
    Sahara中的数据模型
  • 原文地址:https://www.cnblogs.com/zhiji6/p/2996351.html
Copyright © 2011-2022 走看看