使用Gradle的JAR中的META-INF /服务
我想构建一个可以加载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 it = ServiceLoader.load(PluginService.class).iterator();
该迭代器将允许您访问ServiceLoader
找到的所有插件。
出于某种原因,Gradle默认情况下不会将文件包含到META-INF
目录中。 有没有办法让生成的JAR包含这样的文件?
我已经在类Jar
找到了方法metaInf
。 但我不知道groovy足以找到我自己的解决方案。
你将META-INF/services/org.example.plugins.PluginService
放在src/main/java
,但它不是源文件,它是一个资源文件,因此它应该根据Maven目录布局约定放在resources文件夹中,即
src/main/resources/META-INF/services/org.example.plugins.PluginService
在这种情况下,一切都应该开箱即用。
与此同时,我在一个(有点) 类似的问题中找到了我的问题的解决方案。
将以下内容添加到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
希望他们能像jar一样在jar任务中实现这一点。 有人已经开始研究它: http : //fgaliegue.blogspot.fr/2013/06/gradle-serviceloader-support.html
如果您碰巧inheritance了一些不遵循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' } } }
您可以试试这个: https : //plugins.gradle.org/plugin/com.github.harbby.gradle.serviceloader
用法
serviceLoader { serviceInterface 'org.example.plugins.PluginService' serviceInterface 'org.example.plugins.PluginService2' }