Java 依赖注入标准

JSR-330 是 Java 的依赖注入标准。定义了如下的术语描述依赖注入:

  • A 类型依赖 B类型(或者说 B 被 A 依赖),则 A类型 称为”依赖(物) dependency”
  • 运行时查找依赖的过程,称为”解析 resolving“依赖
  • 如果找不到依赖的实例,称该依赖是”不能满足的 unsatisfied”
  • 在”依赖注入 dependency injection”机制中,提供依赖的工具称为”依赖注入器 dependency injector,注射器”

在标准中, 依赖是类型而不是实例/对象; 在程序中(运行时), 需要的是依赖的实例.

javax.inject

包 javax.inject 指定了获取对象的一种方法,该方法与构造器、工厂以及服务定位器(例如 JNDI))这些传统方法相比可以获得更好的可重用性、可测试性以及可维护性。此方法的处理过程就是大家熟知的依赖注入,它对于大多数应用是非常有价值的。

@Inject

注解 @Inject
标识了可注入的构造器、方法或字段。可以用于静态或实例成员。一个可注入的成员可以被任何访问修饰符(private、package-
private、protected、public)修饰。注入顺序为构造器,字段,最后是方法。超类的字段、方法将优先于子类的字段、方法被注入。对于
同一个类的字段是不区分注入顺序的,同一个类的方法亦同

Provider

接口 Provider 用于提供类型 T 的实列。Provider 是一般情况是由注入器实现的。对于任何可注入的 T 而言,您也可以注入 Provider。与直接注入 T 相比,注入 Provider 使得:

  • 可以返回多个实例。
  • 实例的返回可以延迟化或可选
  • 打破循环依赖。
  • 可以在一个已知作用域的实例内查询一个更小作用域内的实例。
1
2
3
4
5
6
7
    class Car {
@Inject Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();

}
}
  • get()
    用于提供一个完全构造的类型 T 的实例。
    异常抛出:RuntimeException —— 当注入器在提供实例时遇到错误将抛出此异常。例如,对于一个可注入的成员 T
    抛出了一个异常,注入器将包装此异常并将它抛给 get()
    的调用者。调用者不应该尝试处理此类异常,因为不同注入器实现的行为不一样,即使是同一个注入器,也会因为配置不同而表现的行为不同。

@Qualifier

用于标识限定器注解。任何人都可以定义新的限定器注解。一个限定器注解:

  • 是被 @Qualifier、@Retention(RUNTIME) 标注的,通常也被 @Documented 标注。
  • 可以拥有属性。
  • 可能是公共 API 的一部分,就像依赖类型一样,而不像类型实现那样不作为公共 API 的一部分。
  • 如果标注了 @Target 可能会有一些用法限制。本规范只是指定了限定器注解可以被使用在字段和参数上,但一些注入器配置可能使用限定器注解在其他一些地方(例如方法或类)上。

@Named

  • 基于 String 的[限定器]

@Scope

  • 用于标识作用域注解。一个作用域注解是被标识在包含一个可注入构造器的类上的,用于控制该类型的实例如何被注入器重用。缺省情况下,如果没有标识作用域注解,注入器将为每一次注入都创建(通过注入类型的构造器)新实例,并不重用已有实例。如果多个线程都能够访问一个作用域内的实例,该实例实现应该是线程安全的。作用域实现由注入器完成。

@Singleton

  • 标识了注入器只实例化一次的类型。该注解不能被继承