META-INF/услуги в 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 такой файл?
Я уже нашел метод metaInf
в классе Jar
. Но я не знаю groovy достаточно хорошо, чтобы найти решение самостоятельно.
Ответы
Ответ 1
Вы размещаете META-INF/services/org.example.plugins.PluginService
в src/main/java
, но это не источник, это файл ресурсов, поэтому его следует поместить в папку ресурсов в соответствии с соглашением макета каталога Maven, то есть
src/main/resources/META-INF/services/org.example.plugins.PluginService
В этом случае все должно работать из коробки.
Ответ 2
Тем временем я нашел решение своей проблемы в (несколько) аналогичном Вопросе.
Добавление следующего в файл 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
Ответ 3
Надеюсь, они будут реализовывать это в задании в банке, как это делает ant. Кто-то уже работал над этим: http://fgaliegue.blogspot.fr/2013/06/gradle-serviceloader-support.html
Ответ 4
Если вам наследовать некоторый код устаревшего кода ant, который не соответствует правилам maven, может помочь следующее.
Определите исходные установки в соответствии с устаревшей структурой и включите следующую строку:
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' }
}
}