2016-06-29 5 views
0

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

Исходный код (com.otabi.firestar.pajamatale.plugin.loader.PluginFinder класс): https://github.com/firestar115/PajamaTale

Плагин: https://github.com/firestar115/PajamaTest

Что я здесь делаю неправильно? Почему плагин не появляется и не печатает «Test Kappa»?

+0

В чем вопрос? –

+0

Как я могу иметь JAR-файлы, которые не находятся в моем классе, отображаются в ServiceLoader? @NicolasFilotto – TsundereBug

ответ

1

Вам нужно создать экземпляр URLClassLoader, к которому вы предоставите URL из каталогов, которые содержат плагин с контекстом ClassLoader как исходный ClassLoader (я имею в виду Thread.currentThread().getContextClassLoader()) и использовать ServiceLoader.load(Plugin.class, myURLClassLoader) вместо ServiceLoader.load(Plugin.class), который использует внутренне контекст ClassLoader который в вашем случае недостаточно, поскольку ваши плагины не находятся в вашем пути к классам.

Что-то вроде:

ClassLoader myURLClassLoader = new URLClassLoader(
    new URL[]{new File("plugins").toURI().toURL()}, 
    Thread.currentThread().getContextClassLoader() 
); 
ServiceLoader<Plugin> loader = ServiceLoader.load(Plugin.class, myURLClassLoader); 
+0

Итак, в основном 'ServiceLoader.load (новый URLClassLoader (" plugins/"))'? – TsundereBug

+0

да, это идея с загрузчиком классов классов как родительский загрузчик классов –

+0

Для создания URL-адреса я использую протокол 'file: //' или просто использую обычный 'плагин'? – TsundereBug

1

Я могу подтвердить, что URLClassLoader требует URL для каждого jar, который представляет Plugin. Это не достаточно, чтобы создать экземпляр класса загрузчика с URL в каталог, содержащий файлы jar. Так что вам нужно сделать:

File[] pluginFiles = directory.listFiles((File dir, String name) -> name.endsWith(".jar")); 
    List<URL> urlsList = new ArrayList<>(); 
    for (File file : pluginFiles) { 
     try { 
      urlsList.add(file.toURI().toURL()); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } 
    } 
    URLClassLoader classLoader = URLClassLoader.newInstance(urlsList.toArray(new URL[]{}), Thread.currentThread().getContextClassLoader()); 

Затем ServiceLoader сможет найти свои плагины.