我有一个非常简单的 POC 设置,我在 Wildfly 9 上部署 JEE7 Web 应用程序。 通过 jaxRs 资源端点,我可以触发“插件加载器”。
PluginLoader 确实使用目录并扫描目录中的 jar 文件,然后将这些 URL 馈送到 URLClassLoader 中。
之后,我使用 ServiceLoader 从这些 URL 加载简单接口(interface)的实现。
当 ServiceLoader 开始迭代找到的实现时,我收到此错误:
Caused by: java.util.ServiceConfigurationError: com.test.MyIface: Provider com.test.MyImpl not a subtype
结构也很简单: MyIface.jar 是接口(interface)。 MyImpl.jar 是 MyIface 的实现,同时它包含一个 META-INF/services 文件,其中包含 MyIface 的正确命名和内容。 当然,Web 应用程序本身只知道 MyIFace。
在 JavaSE 中,使用简单的主入口点并从那里调用加载器,一切正常。 在 JavaEE 中,服务文件似乎被忽略了......至少这是我从异常中得到的。
我把它放在 src/main/resources/META-INF/services 中 并在 src/main/resource/WEB-INF/classes/META-INF/services 中(正如我在 SPI 和 webapps 的上下文中读到的那样)
最佳答案
为了使其发挥作用,必须遵循以下 2 个步骤:
- 实例化一个
ClassLoader
(普通的URLClassLoader
即可),它既知道目标 jar 又 Web 应用程序的类加载器。- 显然需要知道目标 jar 才能加载服务实现
- 它需要将 Web 应用程序的类加载器作为父级,以便所有类加载器共享接口(interface)类;否则,即使自定义类加载器加载了该接口(interface),您也会遇到
ClassCastException
,例如 “MyIface 不是 MyIface 的实例”
- 指定您使用
ServiceLoader.load(Class, ClassLoader)
方法创建的类加载器
关于Java EE WebApp ServiceLoader 将外部 jar 作为插件加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57221944/