使用Gradle的JAR中的META-INF /服务

时间:2012-11-06 15:52:12

标签: java plugins jar gradle

我想构建一个可以加载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文件位于构建路径中,则可以通过调用

来加载插件
Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator();

该迭代器也会让您访问ServiceLoader找到的所有插件。

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

我已在课程Jar中找到方法metaInf。但我不知道groovy足以找到我自己的解决方案。

5 个答案:

答案 0 :(得分:34)

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

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

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

答案 1 :(得分:5)

与此同时,我在(有点)similar Question找到了我的问题的解决方案。

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

答案 2 :(得分:0)

希望他们能像jar一样在jar任务中实现这一点。有人已经开始研究它:http://fgaliegue.blogspot.fr/2013/06/gradle-serviceloader-support.html

答案 3 :(得分:0)

如果您碰巧继承了一些不遵循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' }
    }
}

答案 4 :(得分:0)

嗨,您可以尝试以下操作:https://plugins.gradle.org/plugin/com.github.harbby.gradle.serviceloader

用法

serviceLoader {
    serviceInterface 'org.example.plugins.PluginService'
    serviceInterface 'org.example.plugins.PluginService2'
}