vlambda博客
学习文章列表

Java 模块化编程实践

1. 模块化基础知识

  • jdk 版本需要 9 及以上

  • 在 src/main/java 下添加 module-info.java 文件

  • module-info.java 内容类似于:

module learn.java.modularize {
}

想要了解更多模块化语法信息,请参考 java9之模块化。

2. 模块化实践

基于 Gradle 6.4,参考 Building Modules for the Java Module System

2.1. 启用模块化支持

在 build.gradle 中,添加如下代码:

java {
//告诉 java 编译器一个 Jar 包是一个模块而非传统类库
modularity.inferModulePath = true
}

2.2. 适配原始类库

Jar 包可分为:

  • real module(真模块):按照 java 9 模块化规范构建的 Jar 包,含有module-info.class

  • automatic module(自动化模块):Jar 包的 META-INF/MANIFEST.MF 文件中含有 Automatic-Module-Name 属性,属性值即模块名

  • plain library(原始类库):按照原始方式构建的类库,不符合以上2点规范,也没有模块名

real module 不能直接依赖 plain library,因为 requires 的时候,无法提供 plain library 的模块名。
那么 real module 如果需要依赖 plain library,该怎么办呢?

2.2.1. 借由 automatic module 实现

automatic module 可以依赖 plain library,因为不需要声明依赖。
使用 automatic module 封装 plain library 后,即可向 real module 提供模块名。

2.2.2. 使用插件 extra-java-module-info

每一个 plain library 都需要写一个 automatic module 的封装模块,过于繁琐。
可以通过插件 extra-java-module-info 为 plain library 配置模块信息。

Gradle目前尚未提供extra-java-module-info插件, extra-java-module-info插件仅存在于示例项目 Java Modules with Legacy Libraries Sample 中。

2.3. 如何构建 automatic module

打 Jar 包时,添加 Automatic-Module-Name 属性。在 build.gradle 中添加如下代码:

tasks.jar {
manifest {
attributes('Automatic-Module-Name': 'learn.java.modularize.automatic-module')
}
}

3. 示例项目

本文示例项目位于 learn-java-modularize

  • real-module:演示使用 module-info.java 的真模块

  • automatic-module:演示使用 Automatic-Module-Name 的自动化模块

  • extra-java-module-info:演示使用 extra-java-module-info 插件的真模块

4. 小技巧

一些 Jar 包的低版本是 plain library,但高版本会是 automatic module 或者 real module。

比如 junit:

  • junit:junit:4.12:plain library

  • junit:junit:4.14:automatic module

  • org.junit.jupiter:junit-jupiter-engine:5.6.2 :automatic module

5. 后续问题

  1. jdk 各版本目前使用占比

  2. java 模块化目前使用情况

  3. 封装 extra-java-module-info 插件