java如何处理javax。企业上下文在字段上指定RequestScope时,RequestScope工作?
在代码中找到以下内容(实名替换为虚拟):
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
。但却找不到它的工作原理
问题1:如果我在将由容器注入的字段上指定@RequestScoped
,我会在那里得到请求范围的真实注入实例吗
问题2:如果我将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
}
....
}
# 1 楼答案
我认为
@RequestScoped
和其他作用域仅在指定生产者字段的作用域时才允许在字段(即@Target({ TYPE, METHOD, FIELD })
)上使用,也就是说,它们仅在@Produces
时才有意义:# 2 楼答案
这里发生了很多很多事情。让我们试着一个接一个地解决它们
首先,
@RequestScoped
是一个注释,你把它放在正在制作的东西上。它是一个范围注释,告诉CDI正在制作的东西应该存在多长时间。为了保持简单,这可以是一个Java类:…也可以是生产者方法:
(你可以把它放在一个字段上,但在这种极为罕见的情况下,你的字段现在充当生产者本身。你可以read about producer fields,但除了在某些Java EE场景中,它们几乎总是采取错误的方法。在上面列出的例子中,肯定是采取错误的方法。)
把
@Inject
和@RequestScoped
放在任何东西上都没有任何意义所以你第一个问题的答案是:不
你的第二个问题也可能会被忽略,因为你从来没有在注入场景中使用过范围注释(比如
@RequestScoped
)。您总是在生产场景中使用它们换句话说,当你
@Inject
某物时,根据定义,你基本上不知道你刚刚注入的东西在什么范围内;你只需要把它当作一个普通的POJO使用,CDI会为你提供正确的东西所以在你的情况下,看起来你想要这个:
…以及:
就其本身而言,这是好的,但是
FirstService
有什么范围呢?CDI知道吗这个问题的快速答案分别是:
@Dependent
(因为上面没有其他范围注释)和“可能没有”。这几乎肯定不是你想要的为了进一步挖掘,你现在必须查看档案室中的} is ^{} (可能性很大),那么CDI只会发现上面有bean-defining annotations的类。因此,由于
META-INF/beans.xml
。如果它指出它的^{FirstService
上没有任何类型的注释,它很可能不会被发现,CDI将在运行时或启动时爆炸,表明没有找到FirstService
的依赖项假设我们把
@ApplicationScoped
放在FirstService
上。这将使FirstService
基本上成为一个单例(同样,保持简单)。但是等等,你说,那HttpServletRequest
呢?这将在什么范围内?答案是:作为消费者,你不知道,也不在乎。(真正的答案当然是,它将反映当前的请求,因此很可能在请求范围内。)每当你试图访问HttpServletRequest
字段时,你最好是在请求中,否则它会向你发起攻击或者你可以把
@RequestScoped
放在FirstService
上,在这种情况下,任何访问FirstService
类型字段的东西最好在访问时处于活动的请求范围内,否则,它会再次在你身上爆炸最后,您将在JAX-RS的环境中完成所有这些工作,在CDI诞生之前,JAX-RS有自己的依赖注入框架。要使JAX-RS和CDI能够相对良好地配合使用,需要大量将方形的钉子敲入圆孔。其中一种情况是,严格来说,资源类不支持CDI风格的构造函数注入,只支持JAX-RS风格的构造函数注入,这是它自己的主题(不推荐使用)。因此,对于资源类,您通常希望继续使用字段注入
此外,JAX-RS应用程序不需要Servlet构造。事实上,根据您运行的基础设施的特定组合,} 。(这是它自己的一套问题和答案。)
@Inject private HttpServletRequest request
可能也不起作用,您可能必须使用^{