Как я могу написать свой собственный загрузчик плагинов в java?

Как я могу реализовать плагин в моей программе Java?

Я работаю с Явой. Мой текущий проект связан с электронным оборудованием общего назначения, которое имеет собственный набор команд.

Теперь есть общий графический интерфейс, через который можно получить доступ к оборудованию. Аппаратное обеспечение ведет себя по-разному в разных средах, то есть для разных клиентов. Теперь проблема в том, что графический интерфейс должен иметь возможность добавлять плагины. Плагин означает, что он должен быть способен предоставить определенные возможности клиенту, у которого есть привилегия. Со стороны клиента добавление плагина должно быть простым, например, просто нажмите кнопку, чтобы добавить конкретный объект.

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


person Saneesh A T    schedule 28.09.2011    source источник


Ответы (4)


Вам необходимо предоставить следующие вещи:

  • создайте API, который ваши плагины могут использовать для изменения/расширения поведения вашей программы (ИМХО, это самая сложная часть)
  • определить общую запись для подключаемых модулей, например, файл свойств для подключаемого модуля, определяющий точку входа или точки расширения вашего подключаемого модуля (имя класса класса подключаемого модуля, реализующего интерфейс)
  • динамически загружать плагины из выбранного вами места, например, все файлы *.jar из определенного каталога (взгляните на URLClassLoader)

Предложения API:

  • предпочитать интерфейсы (абстрактным) классам
  • может быть полезно помочь пользователю быстро увидеть, какие интерфейсы он может реализовать (например, IAction, обратите внимание на I в начале), а какие предоставляются вашим приложением для использования плагинов (например, WindowManager)
person Mot    schedule 28.09.2011

Вы можете добавить банку или плагин в приложение в любое время. Для этого не нужно делать ничего особенного.

Если вы используете OGSi, вы можете управлять этим проще, поддерживать несколько версий одной и той же банки и удалять их во время работы приложения. Предлагаю посмотреть на Apache Karaf + iPOJO

person Peter Lawrey    schedule 28.09.2011

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

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

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

public interface PluginInterfaceA {
//Define API here
};

public interface PluginInterfaceB {
// Define API here
};

public interface PluginInterfaceC {
// Define API here
};

public interface PluginFactory {
/**
 * Creates plugin A object.
 */
PluginInterfaceA createPluginA();
/**
 * Creates plugin B object.
 */
PluginInterfaceB createPluginB();
/**
 * Creates plugin C object.
 */
PluginInterfaceC createPluginC();
};

А затем позвольте плагинам определить в файле XML или файле свойств имя класса фабрики плагинов для плагина:

Например, предположим, что ваш плагин определяет:

package com.my.plugin;

public class PluginAImpl implements PluginInterfaceA {
// Code for the class
};

public class PluginBImpl implements PluginInterfaceB {
// Code for the class
};

public class PluginCImpl implements PluginInterfaceC {
// Code for the class
};

public class PluginFactoryImpl implements PluginFactory {
public PluginInterfaceA createPluginA() {
  return new PluginAImpl();
}
public PluginInterfaceB createPluginB() {
  return new PluginAImpl();
}
public PluginInterfaceC createPluginC() {
  return new PluginAImpl();
}
};

А затем определите в файле свойств // Файл plugin.properties, предоставленный в plugin.jar плагина plugin.factory.class = com.my.plugin.PluginFactoryImpl;

В вашем приложении можно сделать

Properties properties = new Properties();
properties.load(this.getClass().getClassLoader().getResourceAsStream("plugin.properties"));

String factoryClass = properties.get("plugin.factory.class");

PluginFactory factory = Class.forName(factoryClass);

PluginInterfaceA interfaceA = factory.createPluginA();
PluginInterfaceB interfaceB = factory.createPluginB();
PluginInterfaceC interfaceC = factory.createPluginC();

// Здесь вызывайте созданные классы по своему усмотрению.

Спасибо, Пабло.

person Pablo Martin Viva    schedule 28.09.2011
comment
Допустим, он хочет предоставить новый плагин, который может быть расширением PluginAImpl или совершенно новым. Как PluginFactoryImpl узнает об этом, не изменяя код? - person Cratylus; 28.09.2011
comment
Я имею в виду, что эти интерфейсы предназначены для классов одного типа плагинов и связаны друг с другом. Скажем, например, что графический редактор хочет поддерживать новую форму, и для этого мне нужно предоставить интерфейс для фигуры, интерфейс для инструмента в палитре. другой для кнопки в пользовательском интерфейсе. Каждый из этих интерфейсов связан с плагином, поэтому абстрактная фабрика создает группы связанных классов, а затем я предоставляю свою фабрику, которая создает мою реализацию этих классов. В моем примере PluginInterfaceA, PluginInterfaceB, PluginInterfaceC являются частью одного и того же плагина, и все они полностью соответствуют плагину. - person Pablo Martin Viva; 29.09.2011
comment
Это моя точка зрения. Вам нужно будет изменить фабрику для каждой новой реализации. - person Cratylus; 29.09.2011
comment
Спасибо, Пабло... Я пытаюсь... - person Saneesh A T; 29.09.2011
comment
Нет, на самом деле вам не нужно модифицировать фабрику для каждой реализации плагина, я фактически кодирую свое приложение в виде набора абстракций с четко определенным интерфейсом и позволяю каждому поставщику плагинов для моего приложения разработать реализацию, поэтому мой код не меняется, когда другой поставщик хочет добавить плагин, просто создайте экземпляр фабрики поставщика с помощью отражения и используйте интерфейс фабрики для создания абстракций для каждого из компонентов плагина. - person Pablo Martin Viva; 30.09.2011
comment
Поскольку я предоставил разработчику плагина поставщика интерфейсы для кода, мое приложение использует только эти интерфейсы, и мое приложение остается неповрежденным и гибким. - person Pablo Martin Viva; 30.09.2011
comment
На самом деле фабрика, которую я предоставляю, представляет собой интерфейс, поэтому с точки зрения моего приложения ничего не меняется, вы, как разработчик плагинов поставщика, создаете реализацию фабрики, которая реализует интерфейс фабрики, предоставленный мной. Единственным контрактом между моим приложением и вашим плагином является интерфейс, который я дал для фабрики, и вы, как реализация плагина, реализуете фабрику таким образом, что ваша фабрика создает экземпляры ваших собственных классов, которые реализуют интерфейсы, которые дает мое приложение. - person Pablo Martin Viva; 30.09.2011

Формат файла JAR имеет свою собственную маленькую систему для управления подключаемыми модулями, который используется в нескольких частях Java SE, включая управление драйверами JDBC. Просто определите интерфейс службы, поместите файлы JAR с реализациями в classpath и загрузите реализации с помощью ServiceLoader.load.

person gustafc    schedule 28.09.2011