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

kon*_*ski 13 java java-ee ejb-3.0

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

我经常可以在网上看到使用@Stateless@Stateful结合的例子@Scoped.他们是什么意思?

编辑:(试图澄清,因为没有人回应这一刻):

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

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

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

编辑2:

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

编辑3: 请在arjan的回答中看到我的评论.

Arj*_*jms 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)注释使它们可用来实现一个步骤.