我正在学习Java EE 8教程,我对范围有一些新手的困惑。我是新手,所以如果这是一个愚蠢的问题,请耐心等待。 我的理解是,CDI 允许将任何已使用作用域(例如@RequestScoped
(注释的类注入到 Servlet 中。 https://javaee.github.io/tutorial/cdi-basic001.html 教程中给出的示例是
@RequestScoped
public class MessageB implements Message { ... }
这允许这样做:
@WebServlet("/cdiservlet")
public class NewServlet extends HttpServlet {
@Inject private Message message;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.getWriter().write(message.get());
}
}
这一切都非常好,很容易理解,但是....
我的问题是,这不会绑定和/或限制 MessageB 类在 servlet 中的使用吗? 如果要用作 CDI Bean 的类需要在一个用例中的请求作用域中使用,在另一个用例中使用 servlet 或应用程序,在另一个用例中使用会话作用域,在另一个用例中可能需要在应用程序作用域中使用,该怎么办? 这应该如何工作?类开发人员作者是否应该设想尽可能广泛的范围(尤其是在编写将被其他开发人员使用的类时(? 如果是这样,如果使用该类的客户端想要在例如请求范围内使用它怎么办? 似乎我们应该有松散耦合的代码,但是将类绑定到范围会限制该类的使用方式,这种方式可能没有用或不合逻辑。 还是总是假设像这样使用的 bean 是由应用程序开发人员自己创作的?
提前感谢您的任何见解。
编辑:更进一步,似乎@Qualifier
是这些问题的解决方案。开发人员需要提供不同的子类型(例如,通过实现接口或扩展类(,然后将@Qualifier
属性用于每个不同的类型。
https://javaee.github.io/tutorial/cdi-basic006.html
https://dzone.com/articles/define-cdi-qualifier
是的,您可以使用不同的 CDI 作用域Message
接口的不同 CDI Bean。这种方法的最佳实践是定义几个注释,例如
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface SessionMessage {}
然后,您可以添加@SessionMessage
例如,在您的@SessionScope
bean 上方,并在此消息 bean 中注入@Inject @SessionMessage private Message message
.
另一种方法是 CDI 的默认@Dependet
作用域,如果未在 CDI Bean 上定义任何作用域,则使用该作用域。使用此范围,您可以实现以下目标:
@Dependent:如果未指定任何对象,则为缺省作用域;这意味着存在一个对象只为一个客户端 (Bean( 提供服务,并且与该客户端 (Bean( 具有相同的生命周期。(https://docs.oracle.com/javaee/6/tutorial/doc/gjbbk.html(
使用此注释,您可以继承客户机 Bean 的作用域。因此,如果您将Message
注入@RequestScoped
豆中,您的Message
将具有相同的生命周期。