java模块边界规范的核心是jpms模块化+接口抽象,通过module-info.java声明导出/依赖,隔离api与实现,配合目录结构和ci检查确保编译期强约束。

Java 中规范模块间调用边界,核心不是只靠 private 或 getter/setter,而是把封装从类级升级到模块级——用 JPMS(Java Platform Module System)配合接口抽象,让“谁可以调用谁”在编译期就确定下来。
用 module-info.java 明确导出与依赖
每个模块必须声明自己开放哪些包、依赖哪些模块。不导出的包,外部模块连编译都过不了:
-
只 exports API 包:比如
order-api模块中写exports com.example.order.api;,但绝不导出com.example.order.internal -
requires 仅声明所需接口模块:订单服务模块写
requires order-api;,但不写requires user-impl这类实现模块 - 禁止跨模块访问非导出类:即使某实现类被意外引入,javac 直接报错,不等到运行时才发现越界
接口定义在独立模块,实现隔离在私有模块
把接口和实现彻底拆开,是控制边界的底层设计原则:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 新建
xxx-api模块(如payment-api),只放PaymentService接口和 DTO 类,不包含任何实现 - 实现模块(如
alipay-impl)requires payment-api,但不exports自己的实现包 - 调用方只依赖
payment-api,通过 DI 注入具体实现,完全感知不到支付宝或微信的细节
包结构配合模块边界强化内聚
目录组织要和模块语义对齐,避免“假模块化”:
- 用
internal/目录存放真正私有的逻辑(如internal.service),并在module-info.java中坚决不导出 - 业务包名体现职责,如
com.example.order.api和com.example.order.domain分开,后者可限制为模块内使用 - 避免在 API 模块里引用实现类、工具类或 Spring 等框架类型——那会把依赖“泄漏”出去
构建与 CI 阶段主动拦截违规调用
光靠约定容易松动,得让机制兜底:
- Maven 编译阶段开启
--illegal-access=deny和--enable-preview(如需)强化检查 - 在 CI 流水线中加入
jdeps分析,扫描 jar 包是否意外依赖了未声明的模块或内部包 - 静态检查工具(如 ArchUnit)编写规则,例如 “service 包下的类不得 import internal 包下的任何类”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










