在Java EE CDI中,如何始终知道CDI bean应该声明为哪个作用域?

时间:2018-08-28 22:46:37

标签: java-ee cdi

我正在逐步完成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());
    }
}

这一切都很好,很容易理解,但是....

我的问题是,这是否不限制和/或限制Servlet中MessageB类的使用?如果要在一个用例,servlet或应用程序的请求范围中使用一个用作CDI bean的类,而在另一个用例中的会话范围中甚至在另一个用例的应用程序范围中使用该类,该怎么办?这应该如何工作?类开发人员的作者是否应该设想尽可能广泛的范围(特别是在编写供其他开发人员使用的类时)?如果是这样,如果使用该类的客户端希望在例如请求范围内使用它,该怎么办? 似乎我们应该具有松散耦合的代码,但是将类绑定到作用域会限制该类可以以无用或逻辑的方式使用的方式。 还是总是假设这样使用的bean是由应用程序开发人员自己编写的?
预先感谢您的任何见解。

编辑:再进一步一点,看来@Qualifier是解决这些问题的方法。开发人员需要同时提供不同的子类型(例如,通过实现接口或扩展类),然后将@Qualifier属性与每种不同的类型一起使用。

https://javaee.github.io/tutorial/cdi-basic006.html

https://dzone.com/articles/define-cdi-qualifier

1 个答案:

答案 0 :(得分:1)

是的,您可以使用不同的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 bean中,则Message将具有相同的生命周期。