Class由于不同的 class 加载器,在同一只耳朵中从两个不同的战争中加载相同的 Class 时抛出异常

ClassCastException when loading same Class from two different wars in same ear, due to different class loaders

我正在处理现有的 ADF 应用程序,其中部署在 weblogic 上的 EAR 中有两个不同的项目模块。
1. 带有 VO、EO 和 AM 的模型项目(包含应用模块实现)
2. UI 项目(war 是使用模型项目的构建文件为此项目创建的)

我添加了另一个 war 文件以启用休息服务以及 UI。 war 不同的原因是 UI war 需要 Web 身份验证,我们希望通过提供多令牌身份验证在 Rest war 中绕过它。 所以现在我们有两个 war 和三个模块。
1.模型项目
2. UI 项目
3. Rest 项目(使用来自 UI 项目和模型项目的构建文件)

现在的问题是使用

检索应用程序模块实现 ApplicationModuleHandle amHandle = Configuration.createRootApplicationModuleHandle("**.**.classpackage","config_name");

amImpl = (MyAMImpl) amHandle.useApplicationModule();

如果 war 中的一个创建了我的 MyAMImpl 的对象,另一个得到

ClassCastException.

我的问题是,是否有任何方法可以使用 weblogic-application.xml 使用相同的 class 加载器加载两个 war。或代码级别的任何其他配置。

P.S。 :我避免使用自定义 class 加载器搞乱我的代码或在应用程序代码中强制使用相同的 class 加载器,因为它是一个现有应用程序。

非常感谢任何帮助。

编辑: 首先是另一个包含单例对象的模块。为了进一步清楚起见,这是一个 Quartz Singleton。 UI 项目包含一个调用应用程序模块的触发器侦听器。

所以我通过大量故障排除找到了原因和解决方案。

原因:两个 war 都使用单独的 class 加载器,并且会创建不同的 Quartz Singleton 实例。每个人也会有自己的 TriggerListener 实例。
因此,当其中一个模块调用 QuartzScheduler 和 Trigger Listener 时,它会创建一个应用程序模块(它在应用程序中持久存在并且不会被释放)。
现在,当第二个应用程序调用 QuartzSingleton 时,会为第二个 class 加载器创建相同的新实例和触发侦听器,但会返回相同的应用程序模块实例。由于第二个 class 加载器不知道返回的应用程序模块,因此它抛出 ClassCastException。

解决方案:在 EAR 级别添加包含 Quartz Scheduler 的项目,并在 war 项目中添加项目的构建输出(这样它们就不会抛出编译时异常)。这将使整个应用程序拥有一个 Quartz Scheduler Singleton 实例,使用应用程序的 Class Loader 实际上是两个 war 的父 class 加载器。这使得 war 能够在父 class 加载器中找到 Class 并且不会抛出异常,因为现在所有三个实例,即 Quartz Scheduler Singleton,TriggerListener 和应用程序模块驻留在相同的 class 加载器中。

P.S。 : 我知道一开始并没有太多解释查询,因为我自己也不确定原因。对此深表歉意。该应用程序存在明显的设计缺陷。它仍然有。希望有人觉得这有用

我在查询中也添加了原因和解决方法。

原因:两个 war 都使用单独的 class 加载器,并且会创建不同的 Quartz Singleton 实例。每个人也会有自己的 TriggerListener 实例。 因此,当其中一个模块调用 QuartzScheduler 和 Trigger Listener 时,它会创建一个应用程序模块(它在应用程序中持久存在并且不会被释放)。 现在,当第二个应用程序调用 QuartzSingleton 时,将为第二个 class 加载器创建相同的新实例和触发侦听器,但返回应用程序模块的相同实例。由于第二个 class 加载器不知道返回的应用程序模块,因此它抛出 ClassCastException。

解决方案:在 EAR 级别添加包含 Quartz Scheduler 的项目,并在 war 个项目中添加项目的构建输出(这样它们就不会抛出编译时异常)。这将使整个应用程序拥有一个 Quartz Scheduler Singleton 实例,使用应用程序的 Class Loader 实际上是两个 war 的父 class 加载器。这使得 war 都能够在父 class 加载器中找到 Class 并且不会抛出异常,因为现在所有三个实例,即 Quartz Scheduler Singleton,TriggerListener 和应用程序模块驻留在相同的 class 加载器中。