6

我刚刚阅读了有关 Java 9 模块系统的信息,我想问一下ServiceLoader. 当应用程序已经启动时,有什么方法可以添加服务实现?删除一些服务实现怎么样?

用例:我将有一些计算某些东西的应用程序。计算算法将在某些服务(Java 9 模块)中定义。是否有任何步骤可以在不停止应用程序的情况下替换此算法?我什么时候更换罐子只是计算会失败,我需要在模块加载完成后捕获错误并重新启动?

有没有其他项目可以支持这样的用例?

4

1 回答 1

0

假设 BankController 是您的服务。如果要从动态路径动态加载其实现,请创建一个新的模块层并加载实现。

private final BankController loadController(final BankConfig config) {
    System.out.println("Loading bank with config : " + JSON.toJson(config));
    try {
        //Curent ModuleLayer is usually boot layer. but it can be different if you are using multiple layers
        ModuleLayer currentModuleLayer       = this.getClass().getModule().getLayer(); //ModuleLayer.boot();
        final Set<Path> modulePathSet        = Set.of(new File("path of implementation").toPath());
        //ModuleFinder to find modules 
        final ModuleFinder moduleFinder      = ModuleFinder.of(modulePathSet.toArray(new Path[0]));
        //I really dont know why does it requires empty finder.
        final ModuleFinder emptyFinder       = ModuleFinder.of(new Path[0]);
        //ModuleNames to be loaded
        final Set<String>  moduleNames       = moduleFinder.findAll().stream().map(moduleRef -> moduleRef.descriptor().name()).collect(Collectors.toSet());
        // Unless you want to use URLClassloader for tomcat like situation, use Current Class Loader 
        final ClassLoader loader             = this.getClass().getClassLoader();
        //Derive new configuration from current module layer configuration
        final Configuration  configuration   = currentModuleLayer.configuration().resolveAndBind(moduleFinder, emptyFinder, moduleNames);
        //New Module layer derived from current modulee layer 
        final ModuleLayer    moduleLayer     = currentModuleLayer.defineModulesWithOneLoader(configuration, loader);
        //create new instance of Implementation, in this case org.util.npci.coreconnect.CoreController implements org.util.npci.api.BankController
        final BankController bankController  = ServiceLoader.load(moduleLayer, BankController.class);
        return bankController;
    } catch (Exception e) {BootLogger.info(e);}
    return null;
}
于 2019-08-24T15:02:45.883 回答