我想我在这里有一个基本的理解问题,我希望有人可以向我解释这个问题。
假设我们有一个有状态的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共享?
谢谢
答案 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。
我做对了吗?