Java EE WebApp ServiceLoader 加载外部 jar 作为插件

Java EE WebApp ServiceLoader loading external jar as plugin

我有一个非常简单的 POC 设置,我在 wildfly 9 上部署了一个 JEE7 webapp。 通过 jaxRs 资源端点,我可以触发 "plugin loader".

PluginLoader 确实使用目录并扫描目录中的 jar 文件,然后将这些 URL 送入 URLClassLoader。

之后,我使用 ServiceLoader 从这些 URL 加载简单接口的实现。

当 ServiceLoader 开始迭代找到的实现时,我收到此错误:

Caused by: java.util.ServiceConfigurationError: com.test.MyIface: Provider com.test.MyImpl not a subtype

结构也很简单: MyIface.jar 是界面。 MyImpl.jar 是 MyIface 的一个实现,同时它包含一个 META-INF/services 文件,其中包含 MyIface 的正确命名和内容。 webapp本身当然只知道MyIFace。

在 JavaSE 中使用一个简单的主入口点并从那里调用加载器,一切正常。 在 JavaEE 中,服务文件似乎被忽略了……至少这是我从异常中得到的。

我放在src/main/resources/META-INF/services 在 src/main/resource/WEB-INF/类/META-INF/services 中(正如我在 SPI 和 webapps 的上下文中读到的那样)

为了使其正常工作,必须遵循以下 2 个步骤:

  1. 实例化一个 ClassLoader(stock URLClassLoader 可以)它知道目标 jar 网络的 classloader应用。
    • 加载服务实现显然需要知道目标jar
    • 它需要将 Web 应用程序的 classloader 作为父级,以便所有 classloader 共享接口 class;否则,即使自定义 classloader 加载界面,你也会 运行 ClassCastException"MyIface is not an instance of MyIface"
  2. 指定您使用 ServiceLoader.load(Class, ClassLoader) 方法创建的 classloader