Как использовать реализацию, загруженную другим загрузчиком классов Java?

StackOverflow https://stackoverflow.com/questions/1758241

  •  20-09-2019
  •  | 
  •  

Вопрос

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

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

Метод 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 является более чистым из двух, поскольку он наиболее похож на то, как вы писали бы код, если бы класс был «обычным» и недоступен через плагин.Однако ни один из них не компилируется.

Варианты, которые я придумал на данный момент:
А.Используйте метод 2, но используйте отражение для вызова метода MethodOnlyInMyImpl (пожалуйста, нет!)
Б.Поместите классы плагина в путь сборки, а затем используйте метод 1, который скомпилируется.(мой нынешний фаворит)
С.B +, когда плагины установлены, скопируйте файлы классов в другой каталог, который находится в пути к классам, чтобы системный загрузчик классов мог их загрузить (вызывает другие проблемы)

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

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

Решение

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

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

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

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

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top