模块的主要作用有:
- 模块间需要显示地声明(模块)依赖,而不是以前的简单的基于 classpath
- 更强的封装隔离,模块不主动导出的话无法被 import;不
open则无法对其使用反射技术
指令
模块通过在模块根目录下的 module-info.java 中的指令来约束使用。
定义模块
最好(或则是必须,没找到规定说明) moduleName 和文件夹名称一致,否则 javac 编译时提示 module 和预期的不一致
module moduleA {
}
引入依赖
requires moduleB;
可加 transitive 来表示依赖传递,如 requires transitive moduleB;,然后在 moduleC 中 requires moduleA; 后,那么在 moduleC 中可使用在 moduleB 中导出的类或接口。
导出 package
exports packageFullName;
表示当别的模块(A) requires 了当前模块,那么 packageFullName 这个包(及子孙包)里的 public 和 protected 的类和接口可在模块 A 里被访问使用。
可用 exports packageFullName to moduleA, moduleB 来表示仅 moduleA 和 moduleB 可访问 packageFullName。
提供服务
provides full.name.Service with full.name.concreateService, full.name.concreateService2;
表示该模块向外提供 full.name.Service 的实现 full.name.concreateService 和 full.name.concreateService2。
使用服务
uses full.name.Service;
表示该模块需要使用 full.name.Service。同时,不直接依赖具体的实现,而是使用抽象类或接口。然后搭配 ServiceLoader 或别的 IoC 工具来做依赖注入,从而达到和具体实现解耦的目的。
配合反射
opens fullPackageName;
表示 fullPackageName 可被使用反射技术。也可使用 opens fullPackageName to moduleA, moduleB 限定开放反射的范围。
open module moduleD {} 表示整个模块都是开放的。
其它
java --list-modules 查看 JDK 内置的模块
编译运行
可通过 javac -d mods --module-source-path src $(find src -name "*.java") 来编译运行(多个模块),src 表示各模块所在的目录。
也可使用 javac -d dist --module-source-path src -m client 来编译指定的模块。