使用 Gradle 的 JAR 中的 META-INF/服务
Posted
技术标签:
【中文标题】使用 Gradle 的 JAR 中的 META-INF/服务【英文标题】:META-INF/services in JAR with Gradle 【发布时间】: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
目录。构建脚本没有什么特别之处。它几乎是一个标准的,包含一些额外的依赖项和一些自定义存储库。
【参考方案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'
【讨论】:
以上是关于使用 Gradle 的 JAR 中的 META-INF/服务的主要内容,如果未能解决你的问题,请参考以下文章
Android Gradle 构建中不使用 libs 文件夹中的 Jar 文件