Mat*_*all 7 java singleton ejb java-ee jboss5.x
前一天,我的应用程序是一个EAR,包含一个WAR,一个EJB JAR和几个实用程序JAR文件.我在其中一个实用程序文件中有一个POJO单例类,它工作正常,并且全世界都很好:
EAR
|--- WAR
|--- EJB JAR
|--- Util 1 JAR
|--- Util 2 JAR
|--- etc.
Run Code Online (Sandbox Code Playgroud)
然后我创建了第二个WAR,并发现(艰难的方式)每个WAR都有自己的ClassLoader,因此每个WAR都会看到不同的单例,并且事情从那里分解.这不太好.
EAR
|--- WAR 1
|--- WAR 2
|--- EJB JAR
|--- Util 1 JAR
|--- Util 2 JAR
|--- etc.
Run Code Online (Sandbox Code Playgroud)
那么,我正在寻找一种方法来创建一个可以跨WAR工作的Java单例对象(跨ClassLoaders?).在@Singleton我发现JBoss 5.1似乎不支持该注释(作为EJB 3.1的一部分添加)之前,EJB注释似乎很有希望.我错过了什么 - 我可以使用@SingletonJBoss 5.1吗?目前无法升级到JBoss AS 6.
或者,我也很高兴不必使用EJB来实现我的单例.我还能做些什么来解决这个问题?基本上,我需要一个半应用程序范围的*钩子到一大堆其他对象,如各种缓存数据和应用程序配置信息.作为最后的手段,我已经考虑将我的两个WAR合并为一个,但这将是非常地狱般的.
*含义:基本上可以在某一层之上的任何地方使用 现在,主要是在我的WAR中 - 视图和控制器(松散意义上).
编辑:我应该真的称它为Java EE而不是J2EE,不应该吗?
编辑2:非常感谢@Yishai的所有帮助.经过一些反复试验后,看起来我已经想出如何在JBoss 5下使用单个ClassLoader来解决这个问题.我在下面详细说明了这个问题,希望其他人也会发现这个问题很有用.
注意,这与JBoss 4下的这一点完全不同(参见Yishai的回答或下面的链接).
不是jboss-web.xml为每个WAR 编写一个,而是为了一个jboss.xmlear-EJB EJB ,而是jboss-classloading.xml在每个WAR中放置一个文件,与DD(web.xml)位于同一位置.内容jboss-classloading.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>
Run Code Online (Sandbox Code Playgroud)
这是来自JBoss CW的,而这里(我认为)适用于JBoss 4.x的是这里描述的.有关JBoss类加载(ing/ers)的更多常规信息:
我可以说,与JBoss 4相比,JBoss社区wiki文档非常缺乏JBoss 5.
Yis*_*hai 11
尽管EJB3.1规范引入了单例,并且您的JBoss版本不支持它,但您可以使用JBoss @Service批注创建单例.这里的说明.此外,您似乎已配置JBoss以隔离您的ejb jar和战争彼此.你不必那样做.您可以查看特定于jboss的xml文件中的loader-repository标记,以便您的整个耳朵共享一个类加载器(或者至少两个战争共享一个类加载器).
所有这一切,我同意@duffymo,在两场战争中分享状态的单身人士是一个想法,你应该走路,如果不是逃避.
编辑:关于单身人士,我建议你看看像这样的问题(在评论中也有一些很好的平衡).
让对象保持缓存状态本身的想法是可以的,特别是对于EJB3,您可以注入状态而不是静态引用它(如果使用@Service注释,那么您需要@Depends JBoss特定注释).话虽这么说,如果你在这里使用"正确"的单例,那么我希望你的WAR有两个独立的类加载器的唯一问题是额外的内存占用.否则你进入了单例的问题区域(必须初始化它们才能使用它们,使用它们的所有东西都必须确保它们首先被初始化,当然所有代码都与它们的初始化高度耦合).
单身者真的很糟糕的地方是他们存储状态,以便一个班级可以改变状态而另一个班级可以改变状态.在3.1之前,它基本上是禁止使用的,即使这样,它也会产生很多并发问题.
编辑(进一步):所以你想要使用classloader存储库.我使用的是JBoss 4.2.3,所以我不一定知道JBoss5的所有细节(虽然他们说它几乎完全可以向后兼容,但它确实重写了它的类加载器),但是在4.2.x默认情况下你的配置没有问题是因为部署在服务器上的所有耳朵共享同一个类加载器("统一类加载器").我怀疑你部署的服务器的配置有所不同,所以我不确定如何与它进行交互,但你需要做的是在你耳边添加一个名为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>
Run Code Online (Sandbox Code Playgroud)
那是JBoss 4.2.5.1具有相同类型的标签,这里是xsd.它具有相同的loader-repository概念.
那应该是它.也就是说,只要您的ejb-jar,战争等没有它,那么他们就不需要它了.但是,你的战争(在jboss-web.xml中 - 与web.xml相同的位置)可能需要相同的东西.在这种情况下,只要您以完全相同的方式命名存储库(如果我理解正确 - 从未尝试过),他们将共享相同的类加载器.对于在jboss.xml中配置的EJB,它与ejb.xml位于同一位置也是如此.
这可能会让它更清晰一些.
| 归档时间: |
|
| 查看次数: |
12473 次 |
| 最近记录: |