文章目录
- JDK9 模块化新特性
- JDK9 模块化入门案例
- JDK9 模块化知识图谱
- 1)模块化语法
- 2)模块化迁移
- 小结
JDK9 模块化新特性
在 JDK9 之前,在日常开发中可能会遇到过以下问题:
- 工程依赖工具包的内部实现类。比如 sun.misc.BASE64Encoder 是 JDK 的内部方法,不属于 JDK 标准库范畴,但在工程代码中可以直接使用,破坏了 JDK 的封装性。
- 类路径地狱。Java 运行时,JVM 会从 jar 包中抽取所有类打平构成一张列表,然后顺序查找类。查找过程可能遇到类冲突(如遇到同名类),若来自不兼容的类,很可能会导致运行时异常,这一切都是未知的。
- 工程打包时包括直接和间接依赖的包。 比如工程在 JDK8 上运行,即使只依赖了部分包,也需要打所有的 JDK8 基础包,无法按需打包。
2017 年 JDK9 引入了“模块化”的概念后,上述问题都得到了一定的解决。模块化将类和资源封装在模块中,仅导出其他模块需要访问的公共包。从概念上可以看出模块化必须遵循三个核心原则:
-
强封装性:隐藏模块实现内部细节,分离供其他模块访问的公开代码
-
定义良好的接口:模块需要向其他模块公开定义良好且稳定的接口
-
显式依赖:模块间的依赖关系可以产生一个模块图:节点表示模块,边缘表示模块间的依赖关系
某种程度上,模块化中模块有些类似于微服务中的应用:微服务应用相对于模块、微服务对外暴露 API 相对于模块公共导出包、微服务的 API 依赖(如maven pom文件)相对于模块的依赖描述符(module-info文件)。
JDK9 模块化入门案例
通过案例学习 JDK9 模块化语法是最快的学习方法,详细示例代码参考:
- Github:https://github.com/zhuqiuhui/Jdk9ModularityExamples(借助于 Intellij Idea 提供了 maven 工程和普通 java 工程两种写法)
示例中 com.zqh.people.api 模块是抽象 api 模块,提供了People 抽象类。com.zqh.people.male 和 com.zqh.people.femal 模块是抽象 api 模块的服务实现,com.zqh.people.client 是客户端模块。相应的模块关系图如下:
附代码结构图(IntelliJ IDEA 2017.3 以上版本支持 JDK9 模块化编程,IDEA 关于 JDK9 支持详细参考:Getting Started with Java 9 Module System):
JDK9 模块化知识图谱
JDK9 模块化知识图谱重点两部分内容:模块化语法和模块化迁移。
1)模块化语法
模块化语法通过上述案例基本掌握,同时案例使用了服务实现来解耦不同的模块实现(provides 和 uses 关键字)。除此之外,JDK9 模块化强调代码的强封装性,不允许访问封装的包以及深度反射其他模块中的代码,这一点对常用的开发框架(如 Spring 依赖注入通过反射初始化Bean)不那么友好,JDK9 提供了开放式模块,即只需在模块描述符中添加关键字 open,就可以开放一个模块(示例如下):
open module com.zqh.people.female {
requires com.zqh.people.api;
provides javamodularity.com.zqh.people.api.People with javamodularity.com.zqh.people.female.Female;
}
与此同时 JDK9 提供了一些命令参数供模块块工作编译和运行,开发过程中可借助于 Intellij Idea 进行开发提效。
2)模块化迁移
JDK8 及以前版本的工程升级到模块化工程的核心思路:先将工程升级到 JDK9,确保工程能在 JDK9 环境上正常运行,再进行模块化迁移。模块化迁移过程中可借助于开放式包、自动模块等 JDK9 提供的特性。另外,在迁移过程中可能需要拆分/聚合包,重点注意点如下:
- 精益化模块:模块应尽可能的小,与外界有定义良好的协议,同时尽可能保持独立
- 模块只能访问通过 requires 语句的公共包,不允许访问封装的包以及深度反射其他模块中的代码
- 模块不允许循环依赖
- 模块系统不允许拆分包。只允许一个模块可以将给定的包导出到另一个模块
- …
小结
据 2023 年 4 月发布的《2023年Java生态系统状况报告》统计,2023 年超过 56% 的应用使用 JDK11(相对于去年 48.44%,前年 11.11%),JDK8 到2023年使用率下降到 32.99%。
上述升级到 JDK9 及以上版本的用户中,真正使用模块化编程的数据不得而知,抛开技术负责人固步自封等主观因素,很多人不升级到最新版本的 JDK最大的原因是:JDK9 全新的模块化机制是 JDK 代码的一大变革。然而模块化的优点是显而易见的,随着 JDK 特性不断的迭代,未来必将有越来越多的库和代码工程支持模块化版本。