Java 平台模块系统入门第 3 部分
介绍
在上一篇指南《Java 平台模块系统入门第 2 部分》中,我介绍了使用模块的示例以及如何将ServiceLoader与模块配合使用。在本系列的最后一篇指南中,我将讨论 Maven 如何使用模块以及一些最后的想法。
那么 Maven 怎么样?
这是一个常见的问题:Maven 和 JPMS 之间有重叠吗?
答案是否定的:它们是相辅相成的。
模块化更多的是关于封装和可见性(即决定哪些包可以在模块/JAR 之外看到),而 Maven 则涉及依赖管理和将代码编译成工件。这两件事在不同的层次上起作用。
在依赖管理方面,每个 Maven 工件都有三个部分:
- 组 ID,唯一标识其所属的项目
- 工件 ID,即工件名称
- 一个版本
JPMS 不知道版本,并且根据命名约定,Java 模块的名称可以与工件 ID、组和工件 ID 的并集相同,或者完全不同。
最重要的是,由于这个原因,我们无法直接将 Java 模块与 Maven POM 依赖项/工件关联。这意味着:
- Maven 无法生成module-info.java文件。
- 在模块化应用程序中,添加依赖项现在涉及两个步骤:
- 像往常一样将依赖项添加到 POM 文件。此依赖项可以模块化也可以不模块化,这并不重要。即使它没有模块化,它也会自动成为模块。
- 依赖项的模块被添加到项目的module-info.java文件中。
例如,假设我们的项目由两个模块组成,一个用于 API,一个用于 GUI,它依赖于 API 模块。
我们可以使用Maven 模块来构建我们的项目。从高层次来看,概念基本相同。父pom.xml如下所示:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Parent project</name>
<modules>
<module>api</module>
<module>gui</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!--
...
-->
</project>
除了maven-compiler-plugin配置之外,与我们习惯的没有什么不同。确保至少使用 3.6.1 版本。
项目的目录结构可以类似如下:
|─ api
| |─ pom.xml
| |─ src
| |─ main
| |─ java
| |─ module-info.java
| |─ my
| |─ example
| |─ api
|─ gui
| |─ pom.xml
| |─ src
| |─ main
| |─ java
| |─ module-info.java
| |─ my
| |─ example
| |─ gui
|- pom.xml
对于 API 模块,pom.xml将如下所示:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>api</artifactId>
<packaging>jar</packaging>
<name>API project</name>
<dependencies>
<!--
...
-->
</dependencies>
<!--
...
-->
</project>
这将是module-info.java文件的内容:
module my.company.api {
exports my.company.api;
// ...
}
现在,在 GUI 模块中,我们必须将对 API 项目的依赖添加到其pom.xml中:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>gui</artifactId>
<packaging>jar</packaging>
<name>GUI project</name>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>api</artifactId>
<version>1.0</version>
</dependency>
<!--
...
-->
</dependencies>
<!--
...
-->
</project>
以及在module-info.java中:
module my.company.webapp {
requires my.company.api;
// ...
}
这样,当构建项目时(例如,使用mvn package),Maven 编译器插件将设置模块路径,以便 Java 编译器能够正常工作。
结论
Java 引入了模块系统,以促进更强大的封装和更好的设计,同时使 Java 成为一种更灵活、更面向未来的语言。孵化器模块等功能将为我们带来新的 API,而这些 API 将在未来的版本中逐渐完成或删除,让我们有机会提供意见。这也非常符合Java 提出的快速发布周期。
在本指南中,您了解了 JPMS 的基础知识;包括模块的好处、它们的工作原理以及它们如何与 Maven 等工具集成。
当然,还有很多东西需要学习,比如自定义运行时映像、如何将类路径项目迁移到模块,或者如何对模块化项目进行单元测试。
我读过的关于 JPMS 的最佳书籍是Sander Mak和Paul Bakker合著的《Java 9 模块化》。我强烈推荐这本书。此外,Nicolai Parlog合著的《Java 模块系统》也是一本在撰写本指南时仍在进行中但前景看好的书籍。如果您将来要使用 Java 9 和 JPMS,请务必参考这些资源。
您可以在此GitHub 存储库中找到带有 ServiceLoader 和 Maven 应用程序的示例 JavaFX 的代码。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~