在Java EE CDI中,如何始终知道CDIbean应该声明为什么范围?



我正在学习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例如,在您的@SessionScopebean 上方,并在此消息 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将具有相同的生命周期。

最新更新