gpt4 book ai didi

java - javax.enterprise.context.RequestScoped 在字段上指定时如何工作?

转载 作者:行者123 更新时间:2023-12-01 19:28:14 24 4
gpt4 key购买 nike

在代码中发现如下(实名替换为dummy):

JAX-RS 资源

@Path("hello")
public class HelloResource {

@Inject
@RequestScoped
FirstService service1;

@Inject
SecondService service2;

....

}

依赖项
// first
public class FirstService {

private static final Logger LOGGER = ...

@Inject
HttpServletRequest request;

....
}

// second
@ApplicationScoped
public class SecondService { .... }

允许声明 @RequestScoped在一个领域。但在任何地方都找不到它是如何工作的。

问题一:如果我指定 @RequestScoped在将由容器注入(inject)的字段上,我会在那里获得请求范围的真实注入(inject)实例吗?

问题二:如果我将 DI 更改为基于构造函数怎么办?我在哪里放 @RequestScoped在这种情况下?
@Path("hello")
public class HelloResource {

private final FirstService service1;
private final SecondService service2;

@Inject
public HelloResource(FirstService service1, SecondService service2) {
// set values here
}

....

}

最佳答案

这里发生了很多很多很多事情。让我们尝试一一解决。

一、@RequestScoped是您对正在制作的东西的注释。它是一个范围注释,告诉 CDI 正在制作的东西应该存在多长时间。尽量保持简单,这可以是一个 Java 类:

@RequestScoped
public class Frobnicator { /* ... */ }

…或者它可以是生产者方法:
@Produces
@RequestScoped
Frobnicator makeRequestScopedFrobnicator() { /* ... */ }

(你可以把它放在一个字段上,但在这种非常罕见的情况下,你的字段现在本身就是一个生产者。你可以 read about producer fields ,但除了在某些 Java EE 场景中,它们几乎总是错误的方法。在你的上面列出的情况,这肯定是错误的做法。)

@Inject@RequestScoped对任何事情都没有任何意义。

所以你的第一个问题的答案是:不。

您的第二个问题也可以通过,因为您从未在注入(inject)场景中使用范围注释(如 @RequestScoped )。您总是在生产场景中使用它们。

换句话说,当你 @Inject东西,根据定义,你基本上不知道你刚刚注入(inject)的东西在什么范围内;您只需将其用作普通的 POJO,CDI 就会为您提供正确的东西。

所以在你的情况下,看起来你想要这个:
@Path("hello")
public class HelloResource {

@Inject
FirstService service1;

@Inject
SecondService service2;

/* etc. */
}

…和:
// We'll talk about the lack of annotations here in a moment
public class FirstService {

private static final Logger LOGGER = ...

@Inject
HttpServletRequest request;

/* etc. */
}

就目前而言这很好,但是 FirstService 的作用域是什么?有? CDI 知道吗?

该问题的快速答案分别是: @Dependent (因为上面没有其他范围注释)和“可能没有”。这几乎肯定不是你想要的。

为了进一步挖掘,您现在必须查看您的 META-INF/beans.xml在文件室 FirstService .如果它表明它的 bean-discovery-mode is annotated ,这很有可能,那么只有具有 bean-defining annotations 的类他们将被 CDI 发现。所以自从 FirstService上面没有任何类型的注释,很可能不会被发现,并且 CDI 将在运行时或启动的某个时间爆炸,表明没有找到 FirstService 的依赖项.

假设我们把 @ApplicationScopedFirstService .这将使 FirstService基本上是一个单例(再次保持简单)。但是等等,你说, HttpServletRequest 怎么样? ?那将在什么范围内?答案是:作为消费者,你不知道,也不在乎。 (真正的答案当然是它会反射(reflect)当前请求,因此很可能在请求范围内。)任何时候您尝试访问 HttpServletRequest字段,你最好在请求中,否则它会炸毁你。

或者你可以把 @RequestScopedFirstService , 在这种情况下任何访问 FirstService -typed 字段最好在访问时处于 Activity 请求范围内,否则,它会再次对您造成影响。

最后,您将在 JAX-RS 的上下文中完成所有这些工作,在 CDI 诞生之前它就有自己的依赖注入(inject)框架。为了使 JAX-RS 和 CDI 能够相对较好地配合使用,需要将大量方形钉子敲入圆孔中。其中一种情况是严格来说资源类不支持 CDI 样式的构造函数注入(inject),仅支持 JAX-RS 样式的构造函数注入(inject),这是它自己的(已弃用)主题。因此,对于资源类,您通常希望保留字段注入(inject)。

此外,JAX-RS 应用程序不需要 Servlet 构造。事实上,根据您运行的基础架构的特定组合, @Inject private HttpServletRequest request也可能不起作用,您可能必须使用 @Context . (这是它自己的一组问题和答案。)

关于java - javax.enterprise.context.RequestScoped 在字段上指定时如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60758747/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com