Реализация динамических плагинов в Java
Я хотел бы реализовать функцию динамического плагина в приложении Java. В идеале:
- Приложение будет определять интерфейс
Plugin
с помощью метода типа getCapabilities()
.
- Плагин будет JAR
pluginX.jar
, содержащий класс PluginXImpl
, реализующий Plugin
(и, возможно, некоторые другие).
- Пользователь помещает
pluginX.jar
в специальный каталог или задает для него параметр конфигурации. Пользователь не обязательно должен включать pluginX.jar
в свой путь к классам.
- Приложение найдет
PluginXImpl
(возможно, через манифест JAR, возможно, путем отражения) и добавьте его в реестр.
- Клиент может получить экземпляр
PluginXImpl
, например, путем вызова метода типа getPluginWithCapabilities("X")
. Пользователь не обязательно должен знать имя плагина.
У меня есть смысл, я должен сделать это с помощью peaberry, но я не могу понять документация. Я потратил некоторое время на изучение Guice, поэтому мой предпочтительный ответ не будет "использовать Spring Динамические модули.
Может ли кто-нибудь дать мне простое представление о том, как это сделать, используя Guice/peaberry, OSGi или просто Java?
Ответы
Ответ 1
На самом деле это довольно просто, используя простой Java:
Поскольку вы не хотите, чтобы пользователь настраивал путь к классам перед запуском приложения, я бы сначала создал URLClassLoader с массивом URL-адресов для файлов в вашем каталоге плагинов. Используйте File.listFiles, чтобы найти все плагины, а затем File.toURI(). ToURL(), чтобы получить URL-адрес для каждого файла. Вы должны передать системный загрузчик классов (ClassLoader.getSystemClassLoader()) в качестве родителя для вашего URLClassLoader.
Если в плагинах-накопителях содержится файл конфигурации в META-INF/services, как описано в документации API для java.util.ServiceLoader, теперь вы можете использовать ServiceLoader.load(Plugin.class, myUrlClassLoader) для запуска загрузчика службы для ваш интерфейс плагина и вызовите iterator() на нем, чтобы получить экземпляры всех настроенных реализаций плагинов.
По-прежнему вам нужно предоставить свою собственную оболочку для фильтрации возможностей плагинов, но я не думаю, что это не должно быть большой проблемой.
Ответ 2
OSGI будет хорошо, если вы захотите заменить плагины во время выполнения i.g. для исправлений в среде 24/7. Я играл некоторое время с OSGI, но это заняло слишком много времени, потому что это не было требованием, и вам нужен план b, если вы удалите пакет.
Тогда мое скромное решение предоставило файлы свойств с именами классов классов дескриптора плагина и позвонил серверу для их регистрации (включая запрос их возможностей).
Это очевидно неоптимально, но я не могу дождаться, чтобы прочитать принятый ответ.
Ответ 3
Вы можете использовать Интерфейс поставщика услуг?
Ответ 4
Лучший способ реализовать плагины с Guice - Multibindings. Связанная страница подробно рассказывает о том, как использовать multibindings для размещения плагинов.
Ответ 5
Извините, если вы это знаете, но посмотрите forName
метод Class. Он используется, по крайней мере, в JDBC для динамической загрузки классов сценариев драйверов, специфичных для СУБД, по имени класса.
Тогда, думаю, нетрудно перечислить все файлы class/jar в каталоге, загрузить каждый из них и определить интерфейс для статического метода getCapabilities()
(или любое имя, которое вы выберете), которое вернет свои возможности/описание в любых условиях и формате, что имеет смысл для вашей системы.