java - 如何在运行时扩展模块路径

标签 java java-9 java-module module-info

我喜欢服务。我也喜欢模块系统。对我来说不幸的是,在我使用 Java 9 之前,我养成了通过 URLClassLoader 从运行时加载的 jar 中获取服务提供者的习惯,就像这样(我将使用 Java 10 的 var 为简洁起见):

var url = new File("myjar.jar").toURI().toURL();
var cl = new URLClassLoader(new URL[] {url}, getClass().getClassLoader());
var services = ServiceLoader.load(MyService.class, cl);
for (var service : services) {
  ...
}

即使在 Java 9 及更高版本中也能正常工作,但它会将 jar 加载到类路径中,这意味着它使用旧的 META-INF\services 方法来查找服务提供者。我宁愿使用 module-info 方法,但这需要将 jar 加载到模块路径上,但我找不到任何方法可以做到这一点。所以我在这里,希望这里有人更透彻地了解模块系统会告诉我如何做到这一点(或者不能,如果是这样的话)。

最佳答案

我可以组装的最小的工作示例是

var path = Path.of("myjar.jar");
var cl = new URLClassLoader(new URL[]{path.toUri().toURL()});
var mf = ModuleFinder.of(path);
var cfg = Configuration.resolve(mf, List.of(ModuleLayer.boot().configuration()), mf, Set.of());
var ml = ModuleLayer.defineModulesWithOneLoader(cfg, List.of(ModuleLayer.boot()), cl).layer();
var services = ServiceLoader.load(ml, MyService.class);
services.forEach(System.out::println);

假设 myjar.jar 是一个模块化的 jar,声明提供 MyService 实现。

关于java - 如何在运行时扩展模块路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54228242/

相关文章:

java - 运行已编译的 Java 类

java - 有没有办法删除 JShell 中的导入?

java - 什么被认为是 Java 核心模块?

java - 如何将 launch4j 与 Java 自定义运行时镜像一起使用?

java - primefaces ajax 从另一种形式更新面板

java - Swing JTabbedPane - 插入内容

java - xjc 和 java 11 : How to enable episode plugin?

Java 9 : Module java. xml.bind 在 Eclipse 中无法访问

java - 不同的用户同时在java hashmap中选择相同的键——它是线程安全的吗?

java - 未找到 gradle Jigsaw 模块