我有这样一个项目:
\---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.java
行 uses 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.
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 useALL-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/