加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

JSR-330 依赖注入

发布时间:2020-12-13 23:14:18 所属栏目:百科 来源:网络整理
导读:这篇是承接《轻量级 Java 开发框架 设计》系列Blog文的后续文章。本文是最新 《Hasor 开发指南》中依赖注入章节的完整内容,开发指南目前仍然在努力编写中。 概念 “依赖注入(DI)”有时候也被称为“控制反转(IoC)”本质上它们是同一个概念。具体是指,当某个

这篇是承接《轻量级 Java 开发框架 设计》系列Blog文的后续文章。本文是最新 《Hasor 开发指南》中依赖注入章节的完整内容,开发指南目前仍然在努力编写中。

概念

“依赖注入(DI)”有时候也被称为“控制反转(IoC)”本质上它们是同一个概念。具体是指,当某个类调用另外一个类的时候通常需要调用者来创建被调用者。但在控制反转的情况下调用者不在主动创建被调用者,而是改为由容器注入,因此而得名。

这里的“创建”强调的是调用者的主动性。而依赖注入则不在需要调用者主动创建被调用者。

举个例子通常情况下调用者(ClassA),会先创建好被调用者(FunBean),然后在调用方法callFoo中调用被调用者(FunBean)的foo方法:

public class ClassA {
    private FunBean funBean = new FunBean();
    public void callFoo() {
        this.funBean.foo();
    }
}
public class FunBean {
    public void foo() {
        System.out.println("say ...");
    }
}

使用了依赖注入的情况恰恰相反,调用者(ClassA)事先并不知道要创建哪个被调用者(FunBean)。ClassA调用的是被注入进来的FunBean,通常我们会为需要依赖注入的对象留有set方法,在调用callFoo方法之前是需要先将funBean对象通过setFunBean方法设置进来的。例如:

public class ClassA {
    private FunBean funBean = null;
    public void setFunBean(FunBean funBean) {
        this.funBean = funBean;
    }
    public void callFoo() {
        this.funBean.foo();
    }
}
public class FunBean {
……

传统注入方式

严格意义上来说注入的形式分为两种,它们是“构造方法注入”和“set属性注入”。我们经常听到有第三种注入方式叫“接口注入”。其实它只是“set属性注入”的一种接口表现形式。

  • A.构造方法注入:是指被注入的对象通过构造方法传入,例如下面代码:
public class ClassA {
    private FunBean funBean = null;
    public ClassA(FunBean funBean) {
        this.funBean = funBean;
    }
    public void callFoo() {
        this.funBean.foo();
    }
}
  • B.set属性注入:是指被注入的对象通过其get/set读写属性方法注入进来,例如:
public class ClassA {
    private FunBean funBean = null;
    public void setFunBean(FunBean funBean) {
        this.funBean = funBean;
    }
    public void callFoo() {
        this.funBean.foo();
    }
}
  • C.接口注入:是指通过某个接口的set属性方法来注入,大家可以看到其本质还是set属性注入。只不过调用者(ClassA),需要实现某个注入接口。
public interface IClassA {
    public void setFunBean(FunBean funBean);
}
public class ClassA implements IClassA{
    private FunBean funBean = null;
    public void setFunBean(FunBean funBean) {
        this.funBean = funBean;
    }
    public void callFoo() {
        this.funBean.foo();
    }
}

Guice与JSR-330

JSR-330相关的API是由“javax.inject.*”软件包提供的一组标准API。通过注解作为其表现形式。Hasor使用Google旗下的开源DI容器Guice作为其JSR-330的标准支持组件。

Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IoC)。Guice非常小而且快。Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数的任意方法,而不仅仅是setter方法)进行注入。

Guice还具有一些可选的特性比如:自定义scopes,传递依赖,静态属性注入,与Spring集成和AOP联盟方法注入等。对于DI框架来说,性能是很重要的,Guice比Spring快这是主流说法,在Guice的官方网站上您可以看到它宣称比Spring快1000倍!

Hasor选用Guice是由于它的开发接口十分灵活,比起Spring而言Guice更适合作为一个内嵌DI工具来使用。

由于Guice是JSR-330标准的实现,这也就使得Hasor也具备了支持JSR-330标准的能力。在下面几个小节会讲解如何使用JSR-330标准将其注入到需要的类上。

我们先假定有一个被调用者(PojoBean),下面是PojoBean类的源代码:

public class PojoBean {
    private String uuid    = UUID.randomUUID().toString();
    private String name    = "马三";
    private String address = "北京马连洼街道办...";
    public String getUuid() {
        return uuid;
    }
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
    ……
}

构造方法注入

public class ConstructorInject {
    private PojoBean userBean;
    @javax.inject.Inject/*依赖注入*/
    public ConstructorInject(PojoBean userBean) {
        this.userBean = userBean;
    }
    public String getUserName() {
        return this.userBean.getName();
    }
}

属性方式注入

public class MethodInject {
    private PojoBean userBean;
    @javax.inject.Inject/*依赖注入*/
    public void setUserBean(PojoBean userBean) { 
        this.userBean = userBean;
    }
    public String getUserName() {
        return this.userBean.getName();
    }
}

字段方式注入

字段注入是DI容器对“set属性注入”的一种改进.这种改进使得被注入的对象不在需要实现一个set方法,DI容器会主动的将要注入的对象赋值到给定的字段上。

public class FieldInject {
    @javax.inject.Inject/*依赖注入*/
    private PojoBean userBean;
    public String getUserName() {
        return this.userBean.getName();
    }
}

单例Bean

单例,通常是指整个应用程序范围内某个类型对象只有一个。Hasor使用AppContext接口表示一个应用程序,在一个AppContext内Hasor通过下面这样的代码可以保证单例:

@javax.inject.Singleton/*声明单例*/
public class SingletonBean {
    private long time = 0;
    public SingletonBean() {
        time = System.currentTimeMillis();
    }
    public void foo() {
        System.out.println("create at time:" + time);
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读