Подтвердить что ты не робот

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 достаточно хорошо, чтобы найти решение самостоятельно.

4b9b3361

Ответ 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

Ответ 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' }
    }
}