带有Gradle的JAR中的META-INF/服务

2022-09-01 10:32:52

我想构建一个插件模块,可以使用ServiceLoader加载。这需要向目录中添加一个文件,该文件以服务接口命名,并包含实现它的类的限定路径。然后,您可以通过调用 来加载这些服务。META-INF/servicesServiceLoader.load()

下面是一个示例:

假设我们要提供一个名为 的插件接口。然后,我们在类中提供此服务的实现。org.example.plugins.PluginServiceorg.example.plugins.impl.ExamplePlugin

如果我们想有某种插件机制,我们可以创建一个包含实现的JAR文件。此 JAR 文件还必须包含该文件 。此文件必须包含一行META-INF/services/org.example.plugins.PluginService

org.example.plugins.impl.ExamplePlugin

以启用 以查找实现。如果该 JAR 文件位于构建路径中,则可以通过调用ServiceLoader

Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator();

该迭代器将为您提供访问.ServiceLoader

出于某种原因,默认情况下,Gradle 不会将文件包含在目录中。有没有办法让生成的JAR包含这样的文件?META-INF

我已经在类中找到了metaInf方法。但是我对时髦的了解还不够好,无法自己找到解决方案。Jar


答案 1

您放入 ,但它不是源,而是资源文件,因此应根据 Maven 目录布局约定将其放置在资源文件夹中,即META-INF/services/org.example.plugins.PluginServicesrc/main/java

src/main/resources/META-INF/services/org.example.plugins.PluginService

在这种情况下,一切都应该开箱即用。


答案 2

与此同时,我在一个(有点)类似的问题中找到了解决问题的方法。

将以下内容添加到文件中,解决了我的问题gradle.build

jar {
  from ('./src/main/java') {
    include 'META-INF/services/org.example.plugins.PluginService'
  }
}

现在 JAR 文件看起来如预期的那样

.
|- org
|  `- example
|     `- plugins
|        `- impl
|           `- ExamplePlugin.class
`- META-INF
   |- MANIFEST.MF
   `- services
      `- org.example.plugins.PluginService

推荐