java - 未命名模块通过 ServiceLoader::load 与命名模块交互

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

我有这样一个项目:

\---main
    \---src
        \---com.foo
            \---UnnamedStart.java
\---api
    \---src
        \---com.foo.api
            \---ApiInterface.java
        \---module-info.java
\---impl
    \---src
        \---com.foo.impl
            \---ApiInterfaceImpl.java
        \---module-info.java

UnnamedStart.java 的实现是:

public static void main(String[] args) {
    ServiceLoader<ApiInterface> services = ServiceLoader.load(ApiInterface.class);
    ...
}

请注意,main 是未命名的模块。

api/src/module-info.java 是:

module com.foo.api {
     exports com.foo.api;
}

impl/src/module-info.java是:

更新 1.1 - 下面的代码已更新,请参阅评论,添加了要求

更新 1.2 - 下面的代码已更新,provides A with B 更改为 provides B with A 创建问题时出错,原本是可以的

module com.foo.impl {
     requires com.foo.api; //added (update 1.1)
     provides com.foo.impl.ApiInterface
         with com.foo.api.ApiInterfaceImpl; //vice versa (update 1.2)
}

当我在 UnnamedStart.java 中运行我的代码时,我最终在 services 中没有元素。

我还尝试在 com.foo.api.ApiInterface 中创建一个静态方法:

static List<ApiInterface> getInstances() {
    ServiceLoader<ApiInterface> services = ServiceLoader.load(ApiInterface.class);
    List<ApiInterface> list = new ArrayList<>();
    services.iterator().forEachRemaining(list::add);
    return list;
}

并添加 api/src/module-info.javauses com.foo.api.ApiInterface; 但它给出了相同的结果(无)。

我让它工作的唯一方法是将 main 从未命名模块迁移到命名模块。

<强>1。当未命名模块尝试与命名模块交互时,java 9 如何工作?

<强>2。是否有可能让它工作并保持 main 像未命名的模块?

更新 1.3 - added related project

最佳答案

ServiceLoader::load 照常工作,但还有其他事情。

[简答]

1. 未命名模块命名模块命名模块的读取相同,但已命名模块 无法访问未命名模块 中的类型。

2.您正在尝试从非模块化 JAR 启动应用程序,因此您必须通过 --add-modules com.foo.impl 明确解析所需的模块。 .

请注意,您需要的模块必须在模块图 上(例如,通过--module-path 添加)。

[更多详情]

1. 有 4 种不同类型的模块:内置平台模块、命名模块、自动模块 未命名模块 和每个其中的命名不同于未命名模块

As they wrote 未命名模块命名模块一样对待所有其他模块:

All other modules have names, of course, so we will henceforth refer to those as named modules.

The unnamed module reads every other module. [...]

The unnamed module exports all of its packages. [...] It does not, however, mean that code in a named module can access types in the unnamed module. A named module cannot, in fact, even declare a dependence upon the unnamed module. [...]

If a package is defined in both a named module and the unnamed module then the package in the unnamed module is ignored.

甚至自动模块也是named :

An automatic module is a named module that is defined implicitly, since it does not have a module declaration.

2. Second part of this answer

If you compile non-modular code or launch an application from a non-modular JAR, the module system is still in play and because non-modular code does not express any dependencies, it will not resolve modules from the module path.

So if non-modular code depends on artifacts on the module path, you need to add them manually with the --add-modules option. Not necessarily all of them, just those that you directly depend on (the module system will pull in transitive dependencies) - or you can use ALL-MODULE-PATH (check the linked post, it explains this in more detail).

这个@nullpointer 注释会很有用

Also, the module resolution still needed the impl to be resolved during the startup. To check which you could also make use of the --show-module-resolution flag.

关于java - 未命名模块通过 ServiceLoader::load 与命名模块交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48327898/

相关文章:

java - 是否可以通过 Java 中的 Telegram API 进行邮件发送(不是机器人)

java - 如何将元素集合添加到我的数组?

java - 在 Java 9 中还可以使用 sun.misc.Unsafe 吗?

java - 如何在 JDK 9 或更高版本中获取引导类路径

java - 如何从某一点向前设置文本颜色

java - 末尾带有 null 的集合比较器

java - 在 libfontmanager.dylib 中将 OpenJDK9 与 FreeType @ref 捆绑在一起

java - 有没有办法在jshell中对顶级函数使用方法引用?

java - RMI 服务器 - 模块 RMIServer 没有 "exports Server"到模块 java.rmi

java - 如何在不创建额外测试模块的情况下使用故障保护和 Junit5 测试 JPMS 服务?