Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.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
如何编写JavaEE/EJB单例?_Java_Jakarta Ee_Singleton_Ejb_Jboss5.x - Fatal编程技术网

如何编写JavaEE/EJB单例?

如何编写JavaEE/EJB单例?,java,jakarta-ee,singleton,ejb,jboss5.x,Java,Jakarta Ee,Singleton,Ejb,Jboss5.x,一天前,我的应用程序是一个EAR,包含一个WAR、一个EJBJAR和两个UtilityJAR文件。我在其中一个实用程序文件中有一个POJO singleton类,它工作正常,一切都很好: EAR |--- WAR |--- EJB JAR |--- Util 1 JAR |--- Util 2 JAR |--- etc. 然后我创建了第二次WAR,发现(艰难的方式)每一次WAR都有自己的类加载器,所以每一次WAR都会看到不同的单例,然后事情就从那里开始了。这不太好 EAR |---

一天前,我的应用程序是一个EAR,包含一个WAR、一个EJBJAR和两个UtilityJAR文件。我在其中一个实用程序文件中有一个POJO singleton类,它工作正常,一切都很好:

EAR
 |--- WAR
 |--- EJB JAR
 |--- Util 1 JAR
 |--- Util 2 JAR
 |--- etc.
然后我创建了第二次WAR,发现(艰难的方式)每一次WAR都有自己的类加载器,所以每一次WAR都会看到不同的单例,然后事情就从那里开始了。这不太好

EAR
 |--- WAR 1
 |--- WAR 2
 |--- EJB JAR
 |--- Util 1 JAR
 |--- Util 2 JAR
 |--- etc.
所以,我正在寻找一种方法来创建一个Java单例对象,它可以跨WAR(跨类加载器?)工作。
@Singleton
EJB注释似乎很有前途,直到我发现jboss5.1似乎不支持该注释(它是作为ejb3.1的一部分添加的)。我错过了什么吗?我可以在JBoss5.1中使用
@Singleton
?升级到JBossAS6现在不是一个选项

或者,我也很高兴不必使用EJB来实现我的单例。我还能做些什么来解决这个问题?基本上,我需要一个半应用程序范围的*钩子来连接一大堆其他对象,比如各种缓存数据和应用程序配置信息。作为最后的手段,我已经考虑将我的两场战争合并为一场战争,但那将是相当可怕的

*意思是:基本上可以在某一层以上的任何地方使用;现在,主要是在我的战争中-视图和控制器(在松散的意义上)

编辑:我真的应该调用它而不是J2EE,不是吗


编辑2:再次感谢@Yishai提供的所有帮助。经过一些尝试和错误,我似乎已经知道如何在JBoss5下跨战争使用单个类加载器。为了我自己的缘故,我在下面详细介绍了这一点,希望其他人也会发现这一点很有用

注意,这与JBoss4下的操作有很大不同(请参阅下面的Yishai的答案或我的链接)

不要为每个WAR编写
jboss web.xml
,为ear EJB-JAR编写
jboss.xml
,而是在每个WAR中将
jboss classloading.xml
文件放在与DD相同的位置(
web.xml
)。
jboss classload.xml
的内容应该是:

<?xml version="1.0" encoding="UTF-8"?>
<classloading
    xmlns="urn:jboss:classloading:1.0"
    name="mywar.war"
    domain="DefaultDomain"
    parent-domain="Ignored"
    export-all="NON_EMPTY"
    import-all="true">
</classloading>

这源于JBoss CW,而(我认为)JBoss 4.x的工作原理是这样描述的。关于JBoss类加载(ing/ers)的更多一般信息:


据我所知,与JBoss 4相比,JBoss 5非常缺乏JBoss社区wiki文档。

我会在你的应用服务器上配置一个单独的对象池,这样它只包含一个实例


你为什么要这样做才是真正的问题。听起来你所有的应用程序都将以这种方式耦合。和singleton的应用程序。为什么您认为应该把它带回来?

您可以使用MBean并将其绑定到JNDI,然后在您想使用它的任何地方检索它


MBean可能部署在.sar文件中

尽管EJB3.1规范引入了singleton,并且您的JBoss版本不支持它,但您可以使用JBoss@Service注释创建singleton。说明书另外,您似乎已经将JBoss配置为将ejb JAR和WAR彼此隔离。你不必那么做。您可以查看jboss特定xml文件中的标记,以便整个ear共享一个类加载器(或者至少两个WAR共享一个类加载器)

尽管如此,我同意@duffymo的观点,一个在两场战争中共享状态的单身汉是一个想法,你应该走,如果不是逃跑的话

编辑:关于单身汉,我建议你看看这样的问题(在评论中也有一些很好的平衡)

让对象本身保持缓存状态的想法是可以的,特别是对于EJB3,在EJB3中,您可以注入您的状态,而不是静态地引用它(如果您使用@Service注释,那么您需要@Dependes JBoss特定的注释)。也就是说,如果您在这里使用的是“适当的”单例,那么我认为您的WAR有两个单独的类加载器这一事实的唯一问题是额外的内存占用。否则,您就进入了单例的问题区域(在这里,必须对它们进行初始化才能使用,使用它们的所有东西都必须确保首先对它们进行初始化,当然,所有代码都与它们的初始化高度耦合)

单例真正糟糕的地方是它们存储状态,以便一个类可以更改状态,而另一个类可以选择它。在3.1之前,它在EJB中基本上是一个禁忌,即使在3.1之后,它也会产生很多并发性问题

编辑(进一步):因此您希望使用classloader存储库。我使用JBoss4.2.3,因此我不一定知道JBoss5的所有细节(虽然他们说它几乎完全向后兼容,但它确实重写了它的类加载器),但是在4.2.x中,默认情况下,您的配置不会导致任何问题,因为部署在服务器上的所有EAR都共享同一个类加载器(“统一类加载器”)。我怀疑的是,您部署到的服务器的配置不同,因此我不确定如何与之交互,但您需要做的是在ear中添加一个名为jboss-app.xml的文件(与application.xml位于同一位置),该文件如下所示:

 <?xml version="1.0"?>
 <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 4.2//EN"
        "http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd">
 <jboss-app>
      <loader-repository>
      com.yourcomany:archive=yourear
      </loader-repository>
 </jboss-app>

com.yourcomany:archive=yourear
这就是JBoss4.2。5.1具有相同类型的标签,以下是。它具有相同的加载程序存储库概念

应该是这样。也就是说,只要您的EJBJAR、war等没有它,那么他们就不需要它。但是,您的wars(在jboss-web.xml中-与web.xml位于同一位置)可能需要相同的东西。在这种情况下,只要您以完全相同的方式命名存储库(如果我理解正确-我自己从未尝试过),它们将共享同一个类加载器。在jboss.xml中配置的EJB也是如此,它与EJB.xml位于同一位置

可能会成功