【问题标题】:META-INF/services in JAR with Gradle使用 Gradle 的 JAR 中的 META-INF/服务
【发布时间】:2012-10-26 14:49:30
【问题描述】:

我想构建一个可以用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 足够好,无法自己找到解决方案。

【问题讨论】:

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

标签: java plugins jar gradle


【解决方案1】:

与此同时,我在(有点)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

【讨论】:

  • 我暂时不会接受我自己的答案,因为我认为这只是一种解决方法。就像上面提到的@axtavt,它应该在build.gradle 中没有这些行。
【解决方案2】:

你把META-INF/services/org.example.plugins.PluginService放在src/main/java里面,但是它不是源文件,是资源文件,所以应该按照Maven目录布局约定放在resources文件夹中,也就是

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      如果您碰巧继承了一些不遵循 maven 约定的基于 ant 的遗留代码,以下可能会有所帮助。

      定义您的源集以匹配旧结构,并包含如下一行:

      include 'META-INF/services/**'

      在您的源集中。这种模式是通用的,将获取您所有的元信息服务。

      下面的完整示例。

      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' }
          }
      }
      

      【讨论】:

        【解决方案5】:

        你好可以试试这个:https://plugins.gradle.org/plugin/com.github.harbby.gradle.serviceloader

        用法

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-11-03
          • 2011-10-31
          • 1970-01-01
          • 2016-12-14
          • 1970-01-01
          • 2010-12-31
          • 2013-01-17
          相关资源
          最近更新 更多