Java 9 ServiceLoader runtime module loading and replacement

不羁岁月 提交于 2020-01-01 10:53:28

问题


I just read about Java 9 module system and I'd like to ask about ServiceLoader. Is there any way how to add service implementation when the application is already started? How about removing some service implementation?

Use case: I will have some application that calculates something. The calculation algorithm will be defined in some service(Java 9 module). Are there any steps that can be done to replace this algorithm without stopping the application? When will I replace the jars is it just that the calculation will fail and I will need to catch the error and restart when the module is done loading?

Is there any other project that can support such use case?


回答1:


Lets Assume BankController is your service . If you want to load its implementation dynamically from dynamic path,create a new module layer and load implementation.

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;
}


来源:https://stackoverflow.com/questions/49644752/java-9-serviceloader-runtime-module-loading-and-replacement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!