应用服务器是否能够优化 CDI 实例的范围,或者我们应该自己定义 CDI 范围
Is application server able to optimize scopes of CDI instances or should we define CDI scopes ourselves
最近我们讨论了在微服务兼容项目中使用 CDI API。
关于我们应该如何使用 CDI 存在争论,有两种不同的意见:
- 不使用 CDI 提供的任何注解,让容器决定实例的范围:
public class MyService {
@Inject
private MyLogger logger;
@Inject
private MyDAO myDAO;
@Inject @ElementsById
private MyModel myModel;
并且该服务在 RestContoller 内部使用:
public class MyREST implements MyApi {
@Inject
private MyService myService;
- 对 Rest 和服务层使用 @AppplicationScoped 之类的注释,不要让容器/应用程序服务器决定 bean 的范围。
推进这项工作的最佳方式是什么?应用程序服务器 (Wildfly) 是否能够优化实例的范围,或者我们应该控制 CDI 并自己定义范围。
从CDI 2.0开始,我更喜欢使用annotated
策略来管理CDI bean,不需要将所有bean添加到CDI上下文。
对于Java EE 8/Jakarta EE 8,Eclipse Cargotracker是在Java EE应用程序中使用Java EE组件的官方蓝图示例。
对于 Jaxrs 资源,根据规范,它可以是 CDI @RequestScoped
bean(我更喜欢)、@Stateless
EJB(默认获得事务支持)或 POJO带有特定于 Jaxrs 的 @Path
等
阅读 CDI and Java EE 了解有关 CDI 与遗留 Java EE 组件之间交互的更多信息。
这里有几点要记住。
首先关于容器和 bean 作用域:
let the container decide the scope of the instances
CDI 容器无法真正决定范围 - 如果范围未定义,那么它将总是 使用 @Dependent
,这可能不是您想要的,因为该范围始终为每个注入点创建一个新实例。
Is the application server (Wildfly) able to optimize the scopes of the instances or should we take control over the CDI and define the scopes ourselves.
根据我上面所说的,应该已经很清楚 WildFly 或任何其他服务器都无法真正为您优化范围 - defined in the specification 当没有定义范围时(并且 class 将变成 CDI bean)它将使用 @Dependent
.
其次,bean发现模式:
CDI 容器是否发现bean 取决于bean 发现模式。这在 the following specification section - in short the modes are either all
or annotated
(well, none
too) and depend on whether you have beans.xml
and what's in it and whether you have bean defining annotations 关于你的 to-become-beans-classes 中有详细说明。
最后但同样重要的是,什么是好的做法:
我建议使用隐式 bean 存档方法 - 为此,您甚至不需要 beans.xml
,但您的所有 bean 至少需要一些 bean defining annotation。通过这种方式,您可以最大限度地减少 CDI 容器执行发现和初始化所需的时间,因为它仅适用于您真正 need/want 的 bean,而不是具有试图将所有 classes 转换为的模式 all
符合条件的豆子。
最近我们讨论了在微服务兼容项目中使用 CDI API。
关于我们应该如何使用 CDI 存在争论,有两种不同的意见:
- 不使用 CDI 提供的任何注解,让容器决定实例的范围:
public class MyService {
@Inject
private MyLogger logger;
@Inject
private MyDAO myDAO;
@Inject @ElementsById
private MyModel myModel;
并且该服务在 RestContoller 内部使用:
public class MyREST implements MyApi {
@Inject
private MyService myService;
- 对 Rest 和服务层使用 @AppplicationScoped 之类的注释,不要让容器/应用程序服务器决定 bean 的范围。
推进这项工作的最佳方式是什么?应用程序服务器 (Wildfly) 是否能够优化实例的范围,或者我们应该控制 CDI 并自己定义范围。
从CDI 2.0开始,我更喜欢使用annotated
策略来管理CDI bean,不需要将所有bean添加到CDI上下文。
对于Java EE 8/Jakarta EE 8,Eclipse Cargotracker是在Java EE应用程序中使用Java EE组件的官方蓝图示例。
对于 Jaxrs 资源,根据规范,它可以是 CDI @RequestScoped
bean(我更喜欢)、@Stateless
EJB(默认获得事务支持)或 POJO带有特定于 Jaxrs 的 @Path
等
阅读 CDI and Java EE 了解有关 CDI 与遗留 Java EE 组件之间交互的更多信息。
这里有几点要记住。
首先关于容器和 bean 作用域:
let the container decide the scope of the instances
CDI 容器无法真正决定范围 - 如果范围未定义,那么它将总是 使用 @Dependent
,这可能不是您想要的,因为该范围始终为每个注入点创建一个新实例。
Is the application server (Wildfly) able to optimize the scopes of the instances or should we take control over the CDI and define the scopes ourselves.
根据我上面所说的,应该已经很清楚 WildFly 或任何其他服务器都无法真正为您优化范围 - defined in the specification 当没有定义范围时(并且 class 将变成 CDI bean)它将使用 @Dependent
.
其次,bean发现模式:
CDI 容器是否发现bean 取决于bean 发现模式。这在 the following specification section - in short the modes are either all
or annotated
(well, none
too) and depend on whether you have beans.xml
and what's in it and whether you have bean defining annotations 关于你的 to-become-beans-classes 中有详细说明。
最后但同样重要的是,什么是好的做法:
我建议使用隐式 bean 存档方法 - 为此,您甚至不需要 beans.xml
,但您的所有 bean 至少需要一些 bean defining annotation。通过这种方式,您可以最大限度地减少 CDI 容器执行发现和初始化所需的时间,因为它仅适用于您真正 need/want 的 bean,而不是具有试图将所有 classes 转换为的模式 all
符合条件的豆子。