JSR 376提议的Java模块化方式,在Java 9中发布,适时跟进一下。
目标
先来看下JSR 376的目标,可以简要概况为,
- 让Java在不同类型的计算设备上更适配、易裁剪
- 提高代码安全性与可维护性
- 提升应用性能
实现
直接观察JDK代码结构,JDK 9里对原有代码进行了模块化切分。大致浏览下代码目录,可以看到Java Module信息如何定义。
module-info.java
文件中定义了Module信息,比如,
module java.base {
exports java.io;
exports jdk.internal.jmod to
jdk.compiler,
jdk.jlink;
uses java.lang.System.LoggerFinder;
provides java.nio.file.spi.FileSystemProvider with jdk.internal.jrtfs.JrtFileSystemProvider;
}
module java.se {
requires transitive java.compiler;
}
module java.desktop {
opens javax.swing.plaf.basic to jdk.jconsole;
}
在model-info.java里面引入了exports
、module
、open
、opens
、provides
、requires
、uses
、with
、to
、transitive
关键字。
module
module {module-name}
用于定义当前module-info.java描述的module的名称。
exports
exports {package-name}
、exports {package-name} to {module-name}
,用于声明当前模块下的哪些package被导出。
requires
requires {module-name}
、requires transitive {module-name}
用于声明当前模块依赖哪些模块,transitive
用于表明这种依赖是否可传递。
provides
provides {interface-name} with {class-name}
用于声明当前module是一个service提供者,提供了interface-name
接口定义的具体实现。
uses
uses {interface-name}
声明当前模块使用了指定名称的service,当前模块为对应service的使用者。
JDK文档中可以查看java.util.ServiceLoader<S>
来看具体的service相关概念与实现机制。
open
opens {package-name} to {module-name}
声明当前模块将指定package开放给对应的其它模块。在之前的Java中,通过反射可以后去任意类的成员与函数,加上这个声明之后只有指定模块中的代码才可以进行相应访问。
总结
上面只是简要的看了下Java中的模块怎么定义,通过新提供的这些model-info.java
中关键字的功能,可以看到除了模块化定义本身之外,之前几个概念与用法发生了相应变化。
首先是public
、protected
、private
等描述符的含义发生了变化,public
也有了约束,必须模块间显示进行了声明,否则也是无法访问的。
其次是反射接口的能力,先前可以进行的操作,现在加上了opens ... to ...
这样的模块定义约束。动态能力得到了控制,从接口提供角度来说,避免了不应该的暴露。
实际项目中去使用这套模块机制,大的方向还是很明确的,就是拆分模块。没有这套机制,良好的代码组织也会进行模块切分,估计会比较容易得到应用。