2011-05-16 39 views
12

通常我使用@RequestScoped@SessionScoped(从javax.enterprise.context)使用@Inject注入对象(例如在面部豆类中)。 我也在使用EJB。据我所知,一组无状态EJB副本(池)用于注入对象。有很多副本的原因是为了确保一个EJB实例不被同时访问。在谈到有状态的EJB时(正如我所理解的那样),这样的一个例子必然会涉及具体的注入点。他们使用@EJB(无国籍人士)注入。在EJB中使用@Scoped有什么意义?

我经常可以在网上看到使用@Stateless@Stateful@Scoped一起使用的示例。他们的含义是什么?

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

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

我们也可以使用有状态EJB,在这种情况下,在方法调用期间会保留一个实例。正如我所想,每创建一个对象,它都会被简单地注入一次。 (也有单身EJB,它在所有对象之间共享)。

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

编辑2:

人们可以使用注释的这样的组合,如果类本身被(通过@Inject)机制通过EJB和DI喷射。然而,这是一种特殊情况,而不是优雅。我问你是否知道其他原因。

编辑3: 请参阅我的意见下arjan的答案。

回答

9

@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可以访问'business beans'通常具有的相同类型的服务(主要是事务)。最后,Gavin King(CDI规范负责人)建议始终使用@Inject而不是@EJB。唯一的例外是远程EJB,其中@EJB仍在使用。

EJB和CDI混淆的部分原因是CDI是Java EE中的一个新组件模型,并且还比较新。尽管它们相互融合的很好,但它们仍然是两种不同的组件模型,并不是所有的最佳实践都已经被认识。 Reza Rahman(EJB成员,EJB书籍作者,CDI实现CanDI的作者)建议,EJB模型可能在未来作为一组CDI服务进行改进。事实上,在Java EE 7中,通过将事务服务与EJB分离并通过(CDI)注释使其可用,正在迈出一步。

+0

我不完全明白。 CDI使用@Scoped注释来决定注入哪个实例(之前使用的实例或新实例)。当我们使用@EJB时,我认为注入了某种代理对象。当我们调用该代理对象上的方法时,它会调用池中可用对象的方法 - 如果它是无状态的。如果它是有状态的,那么这样的代理就会保证我们总是处理之前注入的同一个对象。这样的范围可以被理解为“注入点范围”IMO。 @Scoped注释如何应用于此? – 2011-05-17 14:08:50

+0

如果bean是有状态的,那么范围标注实际上用于选择要注入哪个stub-that-point-to-an-instance。如果没有范围,每次都会失去有状态bean的目的,你会得到一个有状态bean的新存根。使用范围的替代方法是从JNDI请求有状态bean,并将其分配给托管bean的实例变量,并将其存储在HTTP会话中等。 – 2011-05-17 17:03:41

+0

这是否意味着如果我在@EJB中注入了ejb(例如)请求作用域面对bean和这样的ejb也被注释@SessionScoped,同一个实例将被注入到一个会话中的所有面的bean? (这将是这样的,如果我用@Inject注入它) – 2011-05-17 17:27:20