2010-01-20 2 views
18

Я хотел бы реализовать динамическую функцию плагина в приложении Java. В идеале:Реализация динамических плагинов в Java

  • Приложение будет определять интерфейс Plugin с помощью метода, такого как getCapabilities().
  • Плагин будет JAR pluginX.jar, содержащий класс PluginXImpl, реализующий Plugin (и, возможно, некоторые другие).
  • Пользователь вводит pluginX.jar в специальный каталог или задает для него параметр конфигурации. Пользователь не обязательно должен включать pluginX.jar в свой путь к классам.
  • Приложение найдет PluginXImpl (возможно, через манифест JAR, возможно, отражением) и добавьте его в реестр.
  • Клиент может получить экземпляр PluginXImpl, например, путем вызова метода, такого как getPluginWithCapabilities("X"). Пользователь не обязательно должен знать имя плагина.

У меня есть смысл, я должен быть в состоянии сделать это с помощью peaberry, но я не могу понять смысл документации. Я потратил некоторое время на изучение Guice, поэтому мой предпочтительный ответ не будет «использовать Spring Dynamic Modules».

Может ли кто-нибудь дать мне простое представление о том, как это сделать, используя Guice/peaberry, OSGi или просто Java?

+0

Peaberry и Spring DM оба слоя над OSGi. OSGi, похоже, делает то, что вы хотите (концептуально), но будет делать это «OSGi-way» и не будет отображаться на ваш точный процесс, поэтому предложение для Google для некоторых учебных пособий OSGi. – SteveD

+1

OSGi выглядит примерно в сто раз сложнее, чем peaberry. Любые ссылки на хорошие учебные пособия? –

ответ

17

Это на самом деле довольно легко, используя обычный 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() на нем, чтобы получить экземпляры всех настроенных реализаций плагина.

Вы по-прежнему должны предоставить свою обертку вокруг этого фильтра, чтобы фильтровать возможности плагинов, но это не должно быть слишком большой проблемой, я полагаю.

+0

Не могли бы вы объяснить это немного подробнее? – stacker

+1

Если у вас нет более детального вопроса. – jarnbjo

+0

@jarnbjo: Это полностью работает! Благодаря! Мне все равно было бы интересно увидеть решение peaberry или OSGi tho ... –

0

Извините, если вы знаете это, но ознакомьтесь с методом forName от Class. Он используется, по крайней мере, в JDBC для динамической загрузки отдельных классов классов драйверов СУБД по имени класса.

Тогда я думаю, что нетрудно перечислить все файлы класса/jar в каталоге, загрузить каждый из них и определить интерфейс для статического метода getCapabilities() (или любое имя, которое вы выберете), которое возвращает их возможности/описание в любых условиях и формате, что имеет смысл для вашей системы.

+0

@ Bandi-T: Я добавил некоторые требования выше в ответ. Я не хочу использовать что-то вроде 'getPluginInstance (" org.example.PluginXImpl ")' или обязательно иметь каталог плагинов в пути к классам. –

+0

@ Крис Конвей: Тогда, извините, это вне меня, я не очень развит на Java. –

1

OSGI будет хорошо, если вы хотите заменить плагины во время выполнения i.g. для исправлений в среде 24/7. Я играл некоторое время с OSGI, но потребовалось слишком много времени, потому что это не было обязательным требованием, и вам нужен план b, если вы удалите пакет.

Мое скромное решение тогда было, предоставляя файлы свойств с именами классов классов дескриптора плагина и позволяя серверу их регистрировать (включая запрос их возможностей).

Это очевидно неоптимально, но я не могу дождаться, чтобы прочитать принятый ответ.

1

Лучший способ реализовать плагины с Guice - Multibindings. Связанная страница подробно рассказывает о том, как использовать multibindings для размещения плагинов.

+1

«Обратите внимание, что этот механизм не может загружать или выгружать плагины во время работы системы». Мне кажется, что Multibindings требуют, чтобы JAR-модули плагина находились в пути к классам, а пользователь указывал классы модуля в файле конфигурации. Возможно, вы можете динамически загружать JAR-файлы в каталог плагинов с помощью ClassLoader, но тогда вам нужно будет использовать что-то вроде Service-загрузчика, чтобы автоматически найти модули. –

Смежные вопросы