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.

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

我已经metaInf在课堂上找到了方法Jar。但是我不知道 groovy 足够好,无法自己找到解决方案。

4

5 回答 5

49

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

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

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

于 2012-11-06T19:23:07.057 回答
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
于 2012-11-06T19:10:44.530 回答
1

如果您碰巧继承了一些不遵循 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' }
    }
}
于 2016-04-26T14:24:39.257 回答
0

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

于 2013-07-16T07:29:46.990 回答
0

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

用法

serviceLoader {
    serviceInterface 'org.example.plugins.PluginService'
    serviceInterface 'org.example.plugins.PluginService2'
}
于 2018-08-21T03:15:21.037 回答