![Quarkus云原生微服务开发实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/908/41309908/b_41309908.jpg)
3.2 使用依赖注入
当在代码中需要引用CDI Bean的对象实例时,最简单的做法是使用注解@javax.inject.In-ject来声明依赖注入点。注入点所引用的对象实例由CDI容器在运行时自动提供。
3.2.1 了解不同的依赖注入方式
CDI规范一共支持三种注入依赖的方式,分别是构造器、字段和初始化方法。每个使用注解@Inject的位置都被称为依赖注入点。
1 构造器注入
对于添加了注解@Inject的构造器,在创建新的实例时,构造器的实际参数对象由容器来提供。在下面的代码中,OrderService类的构造器的OrderRepository类型的参数由容器提供。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/47_01.jpg?sign=1739318735-iGs0vjPvVqkmBruuP0kx6qeoLvnbsrHI-0-95ff6e9734ee04dc029d87db5c12b79e)
值得一提的是,Quarkus的CDI实现对构造器注入进行了简化。构造器上的注解@Inject不是必需的。
2 字段注入
类中的字段也可以添加注解@Inject。下面代码的OrderService类中字段orderRepository的值由容器提供。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/47_02.jpg?sign=1739318735-FAA8AXSkBvmCN2q97MvBsAh8bGIGbeKx-0-ad8d88ad5da340de923ee9130948155d)
3 方法注入
如果方法上添加了注解@Inject,该方法会在实例创建之后被调用。调用时的实际参数对象由容器来提供。下面代码中的OrderService的init方法使用了注解@Inject。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/48_01.jpg?sign=1739318735-gN6nMsxaFFtefLngNVmlVJTTfd9RhqFm-0-0e2c14d60842c3fc84fee7f8a73bba06)
从功能上来说,方法注入的作用类似于@PostConstruct,可以在对象实例创建之后执行一些初始化逻辑。
3.2.2 注入@Dependent作用域的Bean
对于@Dependent作用域的Bean,容器在每个注入点都会创建新的实例。@Dependent作用域与Spring中的prototype作用域的作用是相同的。
下面代码中的Token的作用域是@Dependent。Token的每个对象实例都有唯一的标识符。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/48_02.jpg?sign=1739318735-Q3gvvqoL4zNbUMXLaUrbAnhk8iCkmmcd-0-6e09abffab736885b9a3880d13d369ae)
下面代码中的TokenProvider中声明了两个使用Token类型的注入点,对应于两个不同的Token对象实例。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/48_03.jpg?sign=1739318735-lPAmHNdUAHeU2xwCWSGFrlZPq4sgaMs6-0-e666a90a746563d4a8b645a58a48eea5)
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/49_01.jpg?sign=1739318735-hwESWfNtMfZc3wwXVsQav6cSmZ4ZGufW-0-da775095870432c62c3ebe23298dfd6d)
3.2.3 获取注入点的元数据
在有些情况下,创建对象实例时需要引用当前注入点的相关信息。最常见的例子是创建记录日志的Logger对象。Logger对象一般使用所在类的名称来作为自己的名称。为了访问当前注入点的信息,需要用到接口javax.enterprise.inject.spi.InjectionPoint。该接口的主要方法如表3-2所示。
表3-2 InjectionPoint接口的主要方法
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/49_02.jpg?sign=1739318735-KmOv7oVyDUtBXhofOGWTKeRv7UdIEzJP-0-42438317594ea434c373727985f1b776)
下面代码中的方法createLogger用来创建Logger对象[1]。作为参数的InjectionPoint接口的实例对象由容器在运行时提供。InjectionPoint接口的getMember方法返回注入点所对应的类的成员,再使用getDeclaringClass方法得到类成员所在的类。所获取到的Class对象被传递给Logger.getLogger方法。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/49_03.jpg?sign=1739318735-tBDWGGtE52VP4GHugXaWd48zgBw9ROEh-0-4f199506561a9c377caafc075e3f205e)
下面代码中的OrderService类中以字段的形式注入了Logger类型的对象实例。
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/49_04.jpg?sign=1739318735-M1WLOSsMSI5nyzvGH59jnaSR2KY0PKiq-0-7a27a276f56fd9f574fefbb97aeb75ba)
![](https://epubservercos.yuewen.com/FA8305/21511157508183006/epubprivate/OEBPS/Images/50_01.jpg?sign=1739318735-ciddsYgHefu3tP4KJTd7s6tar9x0zp3E-0-6394413757d9aaebd61ef9c89aefa0a0)