Реализация динамических плагинов в Java - PullRequest
18 голосов
/ 20 января 2010

Я хотел бы реализовать функцию динамического плагина в приложении 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?

Ответы [ 5 ]

17 голосов
/ 21 января 2010

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

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

1 голос
/ 21 января 2010

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

1 голос
/ 21 января 2010

Любой шанс, что вы можете использовать Интерфейс поставщика услуг ?

1 голос
/ 21 января 2010

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

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

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

0 голосов
/ 20 января 2010

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

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

...