将@Scoped与EJB结合使用有什么意义?

时间:2011-05-16 14:08:39

标签: java java-ee ejb-3.0

通常我使用@RequestScoped@SessionScoped(来自javax.enterprise.context)使用@Inject注入对象(例如在faces bean中)。 我也在使用EJB。据我所知,一组无状态EJB副本(池)用于注入对象。存在多个副本的原因是确保不会同时访问EJB的一个实例。在谈到有状态EJB时(同样如我所理解的),这样的一个实例必然会被注入具体的注入点。并且使用@EJB(无状态的)注入它们。

我经常可以在网上看到将@Stateless@Stateful@Scoped结合使用的示例。这是什么意思?

修改(试图澄清,因为没有人回复此时刻):

我特别感兴趣的是这样的范围注释是否会随时改变(以及它们是如何)创建EJB实例的时刻。 根据我的理解:如果我有@EJB注释字段,则在那里注入适当类的对象。如果这样的EJB是无状态的,容器只需从预先创建的实例池中获取自由实例。如有必要,可以调整池的大小。它是无状态的,因为不保证在我们的类的方法调用(即具有包含EJB引用的字段的类)之间保留对象。

我们也可以使用有状态EJB,在这种情况下,在方法调用期间会保留一个实例。我认为,每次创建对象时只需注入一次。 (还有单例EJB,它在所有对象之间共享)。

我在这里找不到EJB的@Scoped注释的目的。

编辑2:

如果要通过EJB和DI(通过@Inject)机制注入类,可以使用这种注释组合。然而,这是特殊情况而不是优雅。我问你是否知道其他原因。

编辑3: 请参阅arjan的回答中的评论。

1 个答案:

答案 0 :(得分:8)

可以显式确定@Stateless或@Singleton bean的范围,以防止其范围自动修改为可能非法的范围。例如。这两种bean类型都不允许是@RequestScoped。有关详细信息,请参阅此链接:http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html/CDI.html

@Stateful很有意义(明确地)作用域。也就是说,如果没有作为程序员的范围,您必须注意调用@Remove带注释的方法。这可能很麻烦,因为这样的bean通常不会在一个方法中使用,你可以在finally块中调用@Remove方法。使用作用域,当作用域结束时,将完全删除bean。

此外,如果没有作用域,则无法始终使用注入来获取对有状态bean的存根的引用。也就是说,每次注入发生时,您都会获得一个新实例。在请求作用域(JSF)支持bean中注入有状态bean时,这尤其麻烦,您可以在几个请求中保留有状态bean。

然后,结合@Named,您还可以直接使用会话bean作为支持bean来展平您的应用程序层(参见例如http://jaxenter.com/java-ee-6-overview-35987-2.html)。显然,在这种情况下你需要一个明确的范围。现在,在较大的应用程序中展平图层可能不是最佳实践,但对于较小的应用程序和/或刚刚开始使用Java EE的人来说,肯定希望将业务逻辑直接放入支持bean。然后要求支持bean可以访问“业务bean”通常具有的相同类型的服务(主要是事务)。

最后,Gavin King(CDI spec lead)建议始终使用@Inject而不是@EJB。唯一的例外是远程EJB,其中仍然使用@EJB。

关于EJB和CDI的部分混淆是CDI是Java EE中的一个新组件模型,但仍然相对较新。虽然它们相互整合得很好,但它们仍然是两种不同的组件模型,并不是所有最佳实践都已经过考虑。 Reza Rahman(EG成员,EJB书籍作者和CDI实现CanDI的作者)建议将来可能将EJB模型改进为一组CDI服务。实际上,在Java EE 7中,通过将事务服务与EJB分离并通过(CDI)注释使它们可用来实现一个步骤。