Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaEE6在有状态EJB之间共享实例_Java_Java Ee 6_Ejb 3.1 - Fatal编程技术网

JavaEE6在有状态EJB之间共享实例

JavaEE6在有状态EJB之间共享实例,java,java-ee-6,ejb-3.1,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_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容器只创建、共享和管理一个实例。有人能给我解释一下吗?还请解释我如何实现同一个EJB实例被多个其他EJB共享


谢谢

我想我把两件事搞混了-@Sessionscoped和@Stateful

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

因此@statefulejb有一个N:1关系(N@statefulejb只属于一个客户机),而@Stateless EJB有一个N:M关系(N@Stateless EJB属于M个客户机)。这意味着一个EJB实例不能通过仅使用@EJB注释来共享@Stateful EJB,而被多个其他EJB共享

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

我说对了吗

我只是读了一些书

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

以及:

别忘了,在你的案例中,我们处理的是两种类型的会话: bean会话和web会话。前者确保一旦你 请求一个有状态bean,它的标识在该bean中保持不变 用户会话。但是当你使用后者时,你有一个网络会话 bean会话的顶部。以确保从中访问相同的bean 2个不同的JSP(或者在重新加载时),需要存储 将bean的标识放入web会话范围


所以你实际上是对的。当您想要使用您的实例时,您必须使用ManagedBean在其他地方检索它,因为EJB实例与此会话上下文相关联。因此,如果您想简化它并确保EJB在每个会话中只存在一次,那么可以使用CDI并用
@javax.enterprise.context.SessionScoped
对EJB本身进行附加注释;是的,你混淆了不同的概念,也混淆了不同的API。。。 我宁愿使用@Injectover@EJB并指定注入实例的范围

@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;
}

当你说“现在当我使用EJB_B”时,你是什么意思?您是如何验证它不是同一个实例的?当我建立EJB_B并查看EJB_a的属性(例如字符串属性)时,EJB_a bean的属性与托管bean实例化的EJB_a的属性不同;在另一个ManagedBean或Java客户机中(远程查找)?EJB在何处实例化并不重要。它从来都不起作用。我试过了。你能解释一下为什么我应该使用@Inject而不是@EJB吗?好的,关于这个主题的深入讨论在:[link]基本上区别因素是
@Inject
总是知道注入对象的范围,并且你确信注入的实例是一个托管实例(这样可以防止令人讨厌的远程bean序列化问题)。使用
@Inject
您可以获得一个(有时是代理的)托管对象,使用
@EJB
您可以获得一个资源,与简单的JNDI查找没有太大区别。我使用EJB3.x已经有一段时间了,我终于发现了这一点。它最终帮助我“共享”跨bean的会话bean实例。如果没有这个,我发现自己在同一个bean中做了很多不相关的工作,并且因为它而变得缓慢和庞大。