我有一个这样的项目:
\---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 - 以下代码已更新,请参阅评论,已添加requires
更新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
答案 0 :(得分:3)
ServiceLoader :: load 像往常一样工作,但还有其他事情。
[简答]
1。 未命名的模块将命名模块读取到命名模块,但命名模块无法访问未命名模块中的类型。
2。您正在尝试从非模块化JAR启动应用程序,因此您必须通过--add-modules com.foo.impl
显式解析所需的模块。
请注意,您所需的模块必须位于模块图上(例如,按--module-path
添加)。
[更多详情]
1. 有4种不同类型的模块:内置平台模块,命名模块,自动模块, 未命名模块它们与未命名的模块
分开命名As they wrote 未命名模块将所有其他模块视为命名模块:
当然,所有其他模块都有名称,因此我们今后将其称为命名模块。
未命名的模块会读取所有其他模块。 [...]
未命名的模块导出其所有包。 [...]但是,它并不意味着命名模块中的代码可以访问未命名模块中的类型。事实上,命名模块甚至不能声明对未命名模块的依赖。 [...]
如果在命名模块和未命名模块中都定义了包,则忽略未命名模块中的包。
即使自动模块也确实是named:
自动模块是一个隐式定义的命名模块,因为它没有模块声明。
如果您编译非模块化代码或从非模块化JAR启动应用程序,则模块系统仍在运行,并且由于非模块化代码不表示任何依赖性,因此它不会从模块路径解析模块。
因此,如果非模块化代码依赖于模块路径上的工件,则需要使用the
--add-modules
option手动添加它们。不一定是所有这些,只是那些你直接依赖的(模块系统会引入传递依赖) - 或者你可以使用ALL-MODULE-PATH
(查看链接的帖子,它会更详细地解释这一点)。
这个@nullpointer评论很有用
此外,模块分辨率仍然需要在启动期间解决impl。要检查哪个也可以make use of the
--show-module-resolution
标记。