Java 9 + 模块化系统 (Project Jigsaw) 实战:从入门到项目重构

VIP/
在 Java 9 之前,我们一直使用的是 ** 类路径(Classpath)** 机制来管理依赖,虽然简单易用,但也带来了诸多痛点:依赖冲突、jar 包冲突、无法控制访问权限、启动加载冗余类等问题。
为了解决这些问题,Oracle 在 Java 9 中正式推出了Java 模块化系统(Jigsaw 项目),它是 Java 平台自诞生以来最重大的架构变革之一。
本文将带你从零入门 Java 模块化系统,包含核心概念、手动搭建模块化项目、IDEA 实战、模块化依赖配置、访问权限控制等实战内容,适合 Java 开发者学习、项目重构使用,全文可直接发布 CSDN。

一、为什么需要 Java 模块化?

1.1 传统 Classpath 的痛点

  1. 依赖地狱:多个版本的 jar 包共存,容易出现类冲突、方法找不到等问题;
  2. 访问失控public就是全局公开,无法对外部隐藏内部实现类;
  3. 启动臃肿:JVM 启动时会加载所有类,哪怕你只用到一小部分;
  4. 无法封装:工具类、内部 API 被随意调用,代码安全性差。

1.2 模块化带来的核心优势

  1. 强封装性:严格控制类的访问权限,只暴露想暴露的接口;
  2. 依赖管理:声明式依赖,明确模块间依赖关系,避免冲突;
  3. 可裁剪 JDK:使用jlink打包最小运行时镜像,体积大幅缩小;
  4. 程序健壮性:编译期检查依赖,提前发现问题,而非运行时崩溃。

二、模块化核心概念

2.1 什么是模块?

模块 = 代码 + 配置文件(module-info.java)
它是比 Jar 包更大的代码组织单元,一个模块包含多个包,通过module-info.java声明:
  • 我依赖谁
  • 我暴露哪些包给外部使用
  • 我提供哪些服务
  • 我使用哪些服务

2.2 核心关键字

表格
关键字 作用
module 定义一个模块
requires 声明依赖其他模块
exports 暴露包给其他模块访问
requires transitive 传递依赖(隐式传递给下游模块)
opens 开放包给反射使用(框架必备)
provides ... with 服务提供
uses 服务消费

2.3 模块命名规范

  • 全小写,使用域名倒置(如com.example.demo
  • 不要使用modulejavajavax开头(JDK 保留)

三、环境准备

  • JDK 9+(本文使用JDK 17,LTS 版本,企业主流)
  • IDEA 2021+(完美支持模块化)
  • Maven/Gradle(可选,本文先纯手工搭建,再讲 Maven 集成)

四、手动搭建第一个模块化项目(零基础入门)

我们创建两个模块,模拟模块间依赖与调用:
  1. module-common:公共模块,提供工具类
  2. module-user:业务模块,依赖 common 模块

4.1 项目结构(必须严格遵守)

模块化项目的核心:src 目录下直接放包 + module-info.java
plaintext
java-modular-demo/
├── module-common/
│   └── src/
│       ├── com/
│       │   └── example/
│       │       └── common/
│       │           └── StringUtils.java  # 工具类
│       └── module-info.java             # 模块描述文件
└── module-user/
    └── src/
        ├── com/
        │   └── example/
        │       └── user/
        │           └── UserService.java  # 业务类
        └── module-info.java             # 模块描述文件

4.2 编写 module-common 模块

1. 工具类 StringUtils.java

java
运行
package com.example.common;

/**
 * 公共工具类
 */
public class StringUtils {

    /**
     * 判断字符串是否为空
     */
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

2. 模块描述文件 module-info.java

java
运行
// 定义模块名
module module.common {
    // 暴露包给外部模块访问
    exports com.example.common;
}

4.3 编写 module-user 模块

1. 业务类 UserService.java

java
运行
package com.example.user;

import com.example.common.StringUtils;

/**
 * 用户业务类
 */
public class UserService {

    public static void main(String[] args) {
        String name = "Java模块化";
        // 调用公共模块的工具类
        if (StringUtils.isEmpty(name)) {
            System.out.println("用户名为空");
        } else {
            System.out.println("用户名:" + name);
        }
    }
}

2. 模块描述文件 module-info.java

java
运行
// 定义模块名
module module.user {
    // 依赖公共模块
    requires module.common;
}

4.4 运行测试

直接运行UserService,控制台输出:
plaintext
用户名:Java模块化
运行成功!模块化项目搭建完成

五、模块化核心特性实战

5.1 访问权限控制(封装性)

如果我们不使用 exports,其他模块无法访问该包下的类,哪怕是public
示例:在module-common中创建一个内部包,不暴露:
plaintext
com.example.common.internal/
    └── InternalUtil.java
module-info.java不导出这个包:
java
运行
module module.common {
    exports com.example.common;
    // 不导出 com.example.common.internal
}
此时module-user无法导入InternalUtil编译直接报错,实现了真正的封装!

5.2 传递依赖 requires transitive

场景:A 依赖 B,B 依赖 C,A 想直接使用 C,无需重复声明requires C
示例:
java
运行
// module.common 模块
module module.common {
    requires transitive module.core;
    exports com.example.common;
}

// module.user 模块
module module.user {
    requires module.common;
    // 无需 requires module.core,自动继承传递依赖
}

5.3 反射兼容 opens

Spring、MyBatis 等框架大量使用反射,模块化默认禁止反射访问非导出包,必须用opens声明:
java
运行
// 开放指定包给反射使用
opens com.example.user.service;

// 开放整个模块给反射使用(不推荐,不安全)
open module module.user {
}

5.4 服务发现 provides/uses

模块化提供了标准的SPI 服务发现机制,替代传统ServiceLoader
  1. 服务接口模块:定义接口
  2. 服务实现模块provides 接口 with 实现类
  3. 服务调用模块uses 接口

六、IDEA + Maven 搭建模块化项目

企业开发基本都用 Maven,这里给出标准配置:

6.1 父 pom.xml

xml
<modules>
    <module>module-common</module>
    <module>module-user</module>
</modules>
<packaging>pom</packaging>

6.2 子模块 pom.xml

无需特殊配置,保持默认,IDEA 会自动识别module-info.java

6.3 注意事项

  • Maven 依赖 ≠ 模块化依赖
  • 必须在module-info.java中声明requires,否则编译报错
  • 依赖的 jar 包如果没有模块化,会变成自动模块(模块名 = 文件名)

七、使用 jlink 打包最小运行时镜像

模块化最大的亮点:打包只包含项目用到的 JDK 模块,体积从几百 MB 降到几十 MB!

7.1 打包命令

bash
运行
jlink 
  --module-path out/production 
  --add-modules module.user 
  --output myapp 
  --strip-debug 
  --compress 2 
  --no-header-files 
  --no-man-pages

7.2 运行

bash
运行
myapp/bin/java -m module.user/com.example.user.UserService
✅ 打包后体积仅 20MB 左右,传统方式打包需要 JDK 环境,而jlink打包后开箱即用

八、模块化常见问题与解决方案

8.1 错误:模块未找到

原因:requires模块名写错,或依赖未添加

解决:检查module-info.java + 项目依赖

8.2 错误:类无法访问

原因:包未使用exports暴露

解决:在模块描述文件中添加exports 包名

8.3 框架反射报错

原因:模块化禁止反射访问未开放包

解决:使用opens 包名开放反射权限

8.4 第三方 Jar 无模块信息

解决:
  • 自动模块:requires jar包名
  • 手动生成模块描述文件

九、总结

Java 模块化系统(Jigsaw)是 Java 现代化的核心特性,它解决了传统 Classpath 的所有痛点,让 Java 项目更健壮、安全、轻量
本文核心知识点:
  1. 模块 = 代码 + module-info.java
  2. 三大核心:requires(依赖)、exports(暴露)、opens(反射)
  3. 严格的访问控制,真正实现代码封装
  4. jlink打包最小运行时,适合云原生、微服务部署
建议:新项目直接使用模块化,老项目逐步重构,拥抱 Java 现代化开发!

购买须知/免责声明
1.本文部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责。
2.若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
3.如果本站有侵犯、不妥之处的资源,请在网站右边客服联系我们。将会第一时间解决!
4.本站所有内容均由互联网收集整理、网友上传,仅供大家参考、学习,不存在任何商业目的与商业用途。
5.本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
6.不保证任何源码框架的完整性。
7.侵权联系邮箱:aliyun6168@gail.com / aliyun666888@gail.com
8.若您最终确认购买,则视为您100%认同并接受以上所述全部内容。

免费源码网 后端编程 Java 9 + 模块化系统 (Project Jigsaw) 实战:从入门到项目重构 https://svipm.com.cn/21427.html

相关文章

猜你喜欢