
3.2 使用依赖注入
当在代码中需要引用CDI Bean的对象实例时,最简单的做法是使用注解@javax.inject.In-ject来声明依赖注入点。注入点所引用的对象实例由CDI容器在运行时自动提供。
3.2.1 了解不同的依赖注入方式
CDI规范一共支持三种注入依赖的方式,分别是构造器、字段和初始化方法。每个使用注解@Inject的位置都被称为依赖注入点。
1 构造器注入
对于添加了注解@Inject的构造器,在创建新的实例时,构造器的实际参数对象由容器来提供。在下面的代码中,OrderService类的构造器的OrderRepository类型的参数由容器提供。

值得一提的是,Quarkus的CDI实现对构造器注入进行了简化。构造器上的注解@Inject不是必需的。
2 字段注入
类中的字段也可以添加注解@Inject。下面代码的OrderService类中字段orderRepository的值由容器提供。

3 方法注入
如果方法上添加了注解@Inject,该方法会在实例创建之后被调用。调用时的实际参数对象由容器来提供。下面代码中的OrderService的init方法使用了注解@Inject。

从功能上来说,方法注入的作用类似于@PostConstruct,可以在对象实例创建之后执行一些初始化逻辑。
3.2.2 注入@Dependent作用域的Bean
对于@Dependent作用域的Bean,容器在每个注入点都会创建新的实例。@Dependent作用域与Spring中的prototype作用域的作用是相同的。
下面代码中的Token的作用域是@Dependent。Token的每个对象实例都有唯一的标识符。

下面代码中的TokenProvider中声明了两个使用Token类型的注入点,对应于两个不同的Token对象实例。


3.2.3 获取注入点的元数据
在有些情况下,创建对象实例时需要引用当前注入点的相关信息。最常见的例子是创建记录日志的Logger对象。Logger对象一般使用所在类的名称来作为自己的名称。为了访问当前注入点的信息,需要用到接口javax.enterprise.inject.spi.InjectionPoint。该接口的主要方法如表3-2所示。
表3-2 InjectionPoint接口的主要方法

下面代码中的方法createLogger用来创建Logger对象[1]。作为参数的InjectionPoint接口的实例对象由容器在运行时提供。InjectionPoint接口的getMember方法返回注入点所对应的类的成员,再使用getDeclaringClass方法得到类成员所在的类。所获取到的Class对象被传递给Logger.getLogger方法。

下面代码中的OrderService类中以字段的形式注入了Logger类型的对象实例。

