JAVA EE 6在有状态EJB之间共享实例

时间:2012-11-29 20:38:17

标签: java java-ee-6 ejb-3.1

我想我在这里有一个基本的理解问题,我希望有人可以向我解释这个问题。

假设我们有一个有状态的EJB_A和一个有状态的EJB_B以及一个有会话的ManagedbeanA:

@Stateful
@LocalBean
public class EJB_A {
}

@Stateful
@LocalBean
public class EJB_B {
  @EJB
  EJB_A ejb;
}
@ManagedBean
@SessionScoped
public class ManagedBeanA {
   @EJB
   EJB_A ejb;
}

在ManagedBeanA中,创建了EJB_A。现在,当我使用EJB_B(EJB_A作为属性)时,EJB_B中会创建一个新的EJB_A实例。它与之前在ManagedBeanA中创建的EJB_A的实例不同。

我不明白,因为我认为有状态EJB的重点是,对于每个客户端,只有一个实例由EJB-Container创建和共享和管理。有人可以向我解释一下吗?还请解释我如何实现EJB的同一个实例由多个其他EJB共享?

谢谢

3 个答案:

答案 0 :(得分:9)

是的,你把不同的概念和不同的APIS混为一谈...... 我宁愿在@EJB上使用@Inject并指定注入实例的范围..

@Stateful
@LocalBean
public class EJB_A {
}

@Stateful
@LocalBean
public class EJB_B {
  @Inject @SessionScoped
  EJB_A ejb;
}
@ManagedBean
@SessionScoped
public class ManagedBeanA {
   @Inject @SessionScoped
   EJB_A ejb;
}

答案 1 :(得分:2)

我刚做了一些阅读here

  

原因是EJB 3.0有状态会话bean的每个lookup()   远程或本地业务接口导致创建新的   豆的身份。从查找返回的每个引用都指向a   不同的有状态会话bean。由打电话者来决定   它如何管理对该引用的访问。通常是网络   应用程序将引用存储在HttpSession或   应用程序范围(ServletContext)范围,用于后续访问。

  

不要忘记在你的情况下我们正在处理两种类型的会话:   bean会话和Web会话。前者确保一旦你   请求有状态的bean,它的身份保持不变   用户会话。但是当你使用后者时,你会有一个网络会话   bean会话的顶部。确保从中访问同一个bean   2个不同的JSP(或者当你重新加载时),你需要存储   bean的标识进入Web会话范围。

所以你确实是对的。当您想要使用您的实例时,您必须使用ManagedBean在其他地方检索它,因为EJB实例与此会话上下文相关联。因此,如果您想简化它并确保每个会话只存在一次EJB,请使用CDI并使用@javax.enterprise.context.SessionScoped另外注释EJB本身;比你可以肯定的那样。

答案 2 :(得分:1)

我想我混淆了两件事 - @Sessionscoped和@Stateful。

@Stateful注释并不意味着每个客户端只创建一个实例。它只是意味着@Stateful-EJB只属于一个客户端,而@ Stateless-EJB可以由多个客户端共享。

因此,@ Stateful-EJB具有N:1关系(N @ Stateful-EJB恰好属于一个客户端),@ Stateless-EJB具有N:M关系(N @ Stateless-EJBS属于M个客户端) 。这意味着只需使用@ EJB-Annotation for @Stateful EJB就不能由多个其他EJB共享EJB实例。

另一方面,似乎每个客户端只创建一次@ Sessionscoped-Managedbean。

我做对了吗?