2009-11-18 4 views
3

Я пишу библиотеку, где я разрешаю людям предоставлять реализации определенных интерфейсов, используя плагиновую фреймворк (это JPF, если вы знакомы). Плагины не сохраняются в пути к классам. Структура предоставляет мне ClassLoader для каждого плагина, поэтому, когда запрашивается реализация с именем MyImpl интерфейса «MyInterface», я могу найти правильный плагин, а затем использовать этот классный загрузчик плагина для загрузки класса, из которого я могу создать экземпляр если я знаю что-то о конструкторе. Все идет нормально.Как использовать реализацию, загруженную разным загрузчиком классов Java?

Однако теперь у меня есть случай, когда мне нужно вызвать метод, доступный только для этой конкретной реализации. Итак, есть два способа, я мог бы попытаться сделать это:

метод 1:

// Makes sure that MyImpl has been loaded, using the custom classloader 
Plugins.getClass(MyInterface.class, "MyImpl"); 
// This line will not compile because MyImpl is not available at build time 
MyImpl foo = new MyImpl(); 
// If I could get this far, this line would work: 
foo.methodOnlyInMyImpl(); 

Метод 2:

// This call will get an instance of MyImpl (already written and tested) 
MyInterface foo = Plugins.getInstance(MyInterface.class, "MyImpl"); 
// Compiler error because there is no MyInterface.methodOnlyInMyImpl method. 
foo.methodOnlyInMyImpl() 

Метод 1 является уборщик из двух, так как это наиболее аналогично тому, как вы должны писать код, если класс был «нормальным» и не доступен через плагин. Однако, ни компиляции.

Опции я придумал до сих пор:
A. Используйте метод 2, но и использовать отражение, чтобы сделать вызов метода methodOnlyInMyImpl (! Пожалуйста, нет)
B. Поместите плагин классов в пути компоновки и затем используйте метод 1, который будет компилироваться. (Мой текущий фаворит)
C. B + при установке плагинов, копировать файлы классов в другой каталог, который находится в пути к классам, так что система Загрузчик классов может загрузить их (вызывает другие проблемы)

Итак, мои вопросы:

  1. Я пропустил еще одну идею, которая лучше?
  2. Если я сделаю B, у меня будут проблемы во время выполнения? В конце концов, класс, использующий MyImpl, предположительно, был бы загружен с помощью системного загрузчика. Итак, как только он увидит MyImpl foo, не будет ли он пытаться загрузить MyImpl с помощью системного загрузчика классов, что не удастся (даже если вызов Plugins.newInstance предоставит экземпляр MyImpl)?

ответ

3

Во-первых, какое преимущество вы получаете от механизма плагина, когда вам нужно реализовать против реальной реализации? Плагин должен реализовать интерфейс, и вы можете использовать реализацию через интерфейс.

Я не похож на JPF, но классы Java никогда не совместимы при загрузке различными загрузчиками классов. Но есть два возможных пути:

  1. Интерфейс находится в вашем загрузчику, плагин имеет свой загрузчик классов загрузчик классов, как родитель, поэтому его интерфейс такой же, как ваша. Код 2 должен работать с этим, когда метод будет разложен в интерфейсе.

  2. Вы можете использовать сериализацию. Это ограниченный путь более полезной передачи объектов данных между независимыми загрузчиками классов. Мне нужно было использовать это для кросс-контекстной диспетчеризации с параметром запроса между двумя веб-папками.

+0

Пример, иллюстрирующий преимущество: у меня есть интерфейсы X и Y. Существует метод X.getY(), который возвращает Y. У меня есть четыре плагина, которые предоставляют реализации Xa и Xb и Y реализации Yc и Yd. Теперь Xa и Xb должны использовать внутреннюю реализацию Yc, поэтому мне нужна конкретная реализация. Приложение может просто взаимодействовать с Xs и Ys, но плагины нуждаются в конкретных реализациях. JPF помогает управлять зависимостями плагина. –

+0

+1 - ОП пытается игнорировать контракт, подразумеваемый использованием интерфейсов. Если плагины являются единственными, которые заботятся о классах реализации, тогда он/она должен будет предоставить доступ к классу реализации во время компиляции, использовать листинг и обработать возможное исключение ClassCastException. – kdgregory

+0

К сожалению, я не могу предвидеть все интерфейсы. Сериализация (Arne), кастинг во время выполнения (kdgregory) и TransLoader (Carl) требуют, чтобы класс был каким-то образом доступным в текущем загрузчике классов, что не в моем случае - оно сводилось к использованию рефлексии или предъявлению требований к времени выполнения classpath для включения плагинов. Я выбрал последний. Принимая этот ответ из-за ключевой фразы, «классы Java никогда не совместимы при загрузке разными загрузчиками классов». Спасибо, я бы добавил +1, если бы у меня был представитель. –

2

Существует библиотека под названием TransLoader, упомянутая в предыдущем вопросе. Вот URL-адрес источника: http://code.google.com/p/transloader/.

+1

Это было полезно и помогло бы, если бы мои требования были разными. Благодарю. Я бы добавил, если бы у меня был представитель. –

+0

+1 back atcha, и, к счастью, у меня есть репутация. Мне жаль, что я не смог более подробно различить и удовлетворить ваши требования. –

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