Есть ли способ обновить модульную библиотеку без обновления основного приложения? - PullRequest
0 голосов
/ 16 мая 2019

До организации модульного приложения у меня было одно основное приложение JavaFX, которое загружало несколько пользовательских библиотек для разных опций и возможностей в основном приложении.

В старом способе реализации я просто отправляю новую библиотеку для обновления, основное приложение читает все библиотеки из папки, и это работает как чудо. Но в модульной системе, если мое приложение хочет использовать новую модульную библиотеку, которую я отправляю, оно должно обновить свой файл информации модуля, кстати, мне нужно отправить обновления для модульной библиотеки и для основного приложения. Представьте себе, это было бы похоже на то, что chrome нужно отправлять обновления браузера для каждого нового создаваемого плагина. Как я вижу, с модульной системой Java вы не можете создавать модульные приложения.

Есть ли способ импортировать новый модуль без обновления основного приложения или каким-либо другим способом?

1 Ответ

0 голосов
/ 17 мая 2019

В Java есть класс для этого: ServiceLoader .

Если мы предполагаем, что у вас есть интерфейс «поставщика услуг» с именем PluginProvider, другие модули могут заявить о себе, чтобы предоставить эту услугу, добавив это в соответствующие дескрипторы module-info.java:

provides com.john.myapp.PluginProvider with com.library.MyProvider;

Тогда ваше приложение заявит, что оно использует эту службу в своей собственной информации модуля:

uses com.john.myapp.PluginProvider;

И код вашего приложения создаст ModuleFinder , который ищет в каталоге (или каталогах), где вы ожидаете, что эти подключаемые модули находятся, а затем передает этот ModuleFinder в Конфигурацию , которая может использоваться для создания ModuleLayer для ServiceLoader:

public class PluginLoader {

    private final ServiceLoader<PluginProvider> loader;

    public PluginLoader() {

        Path pluginDir = Paths.get(System.getProperty("user.home"),
            ".local", "share", "MyApplication", "plugins");

        ModuleLayer layer = PluginProvider.class.getModule().getLayer();
        layer = layer.defineModulesWithOneLoader(
            layer.configuration().resolveAndBind(
                ModuleFinder.of(),
                ModuleFinder.of(pluginDir),
                Collections.emptySet()),
            PluginProvider.class.getClassLoader());

        loader = ServiceLoader.load(layer, PluginProvider.class);
    }

    public Stream<PluginProvider> getAll() {
        return loader.stream();
    }

    public void reload() {
        loader.reload();
    }
}

Возможно, вы даже захотите посмотреть каталог плагинов для новых или удаленных файлов:

try (WatchService watch = pluginDir.getFileSystem().newWatchService()) {

    pluginDir.register(watch,
        StandardWatchEventKinds.ENTRY_CREATE,
        StandardWatchEventKinds.ENTRY_DELETE,
        StandardWatchEventKinds.ENTRY_MODIFY,
        StandardWatchEventKinds.OVERFLOW);

    WatchKey key;
    while ((key = watch.take()).isValid()) {
        loader.reload();
        key.reset();
    }
}
...