【Free style】Java 依赖注入总结

举报
菊花茶 发表于 2017/11/02 17:00:25 2017/11/02
【摘要】 最近在研读Hive社区版本的源码,发现其中多处用到了Java依赖注入,这里简单总结一下依赖注入的几种实现方法。在谈java依赖注入之前,有必要先回顾一下设计模式中的Proxy模式。

最近在研读Hive社区版本的源码,发现其中多处用到了Java依赖注入,这里简单总结一下依赖注入的几种实现方法。在谈java依赖注入之前,有必要先回顾一下设计模式中的Proxy模式。

    其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。先来看看关系图:

image.png

根据上文的阐述,代理模式就比较容易的理解了,我们看下代码:

 public interface Sourceable {
    public void method();
}
 public class Source implements Sourceable {

    @Override
    public void method() {
        System.out.println("the original method!");
    }
}
 public class Proxy implements Sourceable {

    private Source source;
    public Proxy(){
        super();
        this.source = new Source();
    }
    @Override
    public void method() {
        before();
        source.method();
        atfer();
    }
    private void atfer() {
        System.out.println("after proxy!");
    }
    private void before() {
        System.out.println("before proxy!");
    }
}


测试类

 public class ProxyTest {

    public static void main(String[] args) {
        Sourceable source = new Proxy();
        source.method();
    }

}


输出:

before proxy!
the original method!
after proxy!

代理模式的应用场景:

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

 

下面我们要说的Java依赖注入可以说就是proxy模式的一种应用,这里总结一下常用的三种依赖注入方法

1. 接口注入

 

我们常常借助接口来将调用者与实现者分离。如:

 public class ClassA {
private InterfaceB clzB;
public init() {
    Ojbect obj =
    Class.forName(Config.BImplementation).newInstance();
    clzB = (InterfaceB)obj;
}
……
}

 上面的代码中,ClassA依赖于Inte*** ceB的实现,如何获得Inte*** ceB实现类的实例?传统的方法是在代码中创建Inte*** ceB实现类的实例,并将起赋予clzB。而这样一来,ClassA在编译期即依赖于Inte*** ceB的实现。为了将调用者与实现者在编译期分离,于是有了上面的代码,我们根据预先在配置文件中设定的实现类的类名,动态加载实现类,并通过Inte*** ceB强制转型后为ClassA所用。
    这就是接口注入的一个最原始的雏形。而对于一个接口注入型IOC容器而言,加载接口实现并创建其实例的工作由容器完成,如J2EE开发中常用的Context.lookup(ServletContext.getXXX),都是接口注入型IOC的表现形式。
Apache Avalon是一个典型的Type1型IOC容器。

2. 构造子注入


构造子注入,即通过构造函数完成依赖关系的设定,如:

 public class DIByConstructor {
private final DataSource dataSource;
private final String message;
public DIByConstructor(DataSource ds, String msg) {
    this.dataSource = ds;
    this.message = msg;
}
……
}

 可以看到,在Type2类型的依赖注入机制中,依赖关系是通过类构造函数建立,容器通过调用类的构
造方法,将其所需的依赖关系注入其中。
PicoContainer(另一种实现了依赖注入模式的轻量级容器)首先实现了Type2类型的依赖注入模式。


3. 设置注入


    这种方式广泛应用在Spring框架的参数配置中,客户代码仅仅面向接口编程,而无需知道实现类的具体名称。同时,我们可以很简单的通过修改配置文件来切换具体的底层实现类。下面我们抛开Spring框架本身,使用一个简单的例子来实现类似Spring的依赖注入

 public class ActionFactory {
    public static Action getAction(String actionName) {
      Properties pro = new Properties();
      try {
        pro.load(new FileInputStream("config.properties"));
        String actionImplName = (String) pro.get(actionName);
        String actionMessage = (String) pro.get(actionName + "_msg");
        Object obj = Class.forName(actionImplName).newInstance();

        // BeanUtils是Apache Commons BeanUtils提供的辅助类
        BeanUtils.setProperty(obj, "message", actionMessage);
        return (Action) obj;
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (InstantiationException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
      return null;
    }
  }

配置文件则采用最简单的properties文件形式:

TheAction=net.xiaxin.spring.qs.UpperAction

TheAction_msg=HeLLo

测试类:

  public void testFactory(){
    Action action = ActionFactory.getAction("TheAction");
    System.out.println(action.execute("Rod Johnson"));
}

上面的例子中,我们通过设置注入,在运行期动态将字符串“HeLLo” 注入到Action实现类的Message属性中。用同样的方法,我们可以通过修改配置文件让程序调用不同的实现方法,从而实现灵活的依赖注入。在Hive源码中,HiveDriverRunHook类也是使用这种方式实现注入的

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。