使用Gradle构建的JAR文件中的META-INF/services。

37

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

以下是一个示例:

假设我们想提供一个名为org.example.plugins.PluginService的插件接口。我们可以在org.example.plugins.impl.ExamplePlugin类中提供此服务的实现。

如果我们想要一种插件机制,我们可以创建一个JAR文件,其中包含实现。该JAR文件还必须包含文件META-INF/services/org.example.plugins.PluginService,并且该文件必须包含一行内容。

org.example.plugins.impl.ExamplePlugin

要让ServiceLoader找到实现类,你需要将JAR文件加入到构建路径中。如果该JAR文件已经在构建路径中,你可以通过调用以下方法来加载插件:

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

那个迭代器将给您访问 ServiceLoader 找到的所有插件。

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

我已经找到了类 Jar 中的 metaInf 方法。但是,我不够熟练使用 Groovy,无法自行找到解决方案。


1
你确定吗?对我来说很好用。你把这个文件放在哪里,你的 build.gradle 是怎么样的呢? - axtavt
主源文件夹src/main/java中有一个META-INF目录。构建脚本没有什么特别之处,几乎是标准的,包含一些额外的依赖项和一些自定义存储库。 - pvorb
5个回答

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

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

在这种情况下,一切都应该直接奏效。

7

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

将以下内容添加到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

我暂时不接受自己的答案,因为我认为这只是一个解决方法。正如@axtavt在上面所说的那样,在build.gradle中不需要这些行也应该可以工作。 - pvorb

2

如果您继承了一些不遵循Maven约定的基于Ant的旧代码,下面的内容可能会有所帮助。

定义与旧结构相匹配的源集,并在其中包含以下行:

include 'META-INF/services/**'

这个模式是通用的,将捕获所有meta inf服务。

下面是完整的示例。

sourceSets {
    main {
        java {
            srcDir 'src'
            exclude '**/Test*.java'
        }
        resources {
            srcDir 'src'
            include '**/*.xml'
            include 'META-INF/services/**'
        }
    }
    test {
        java {
            srcDir 'src'
            include '**/Test*.java'

        }
        resources { srcDir 'resources' }
    }
}

1

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接