Java 模块系统(Java 9)
Java 模块系统(Java Platform Module System,JPMS)是 Java 9 引入的重要特性,用于管理代码组织和依赖关系。理解模块系统的使用是进行大型项目开发的基础。本章将详细介绍 Java 中的模块系统。
module-info.java
什么是模块
模块是一个命名的、自描述的代码和数据的集合。
模块的特点:
- 有明确的边界
- 声明依赖关系
- 控制导出和访问
module-info.java 文件
**module-info.java**是模块描述文件,位于模块根目录。
module com.example.mymodule {
// 模块声明
}
文件结构:
mymodule/
├── module-info.java
└── com/
└── example/
└── mymodule/
└── MyClass.java
模块声明与导出
基本模块声明
module com.example.mymodule {
// 模块体
}
导出包(exports)
**exports**用于导出包,使其他模块可以访问。
module com.example.mymodule {
// 导出包
exports com.example.mymodule.api;
exports com.example.mymodule.util;
// 其他模块可以访问这些包中的 public 类
}
导出到特定模块(exports ... to)
module com.example.mymodule {
// 只导出给特定模块
exports com.example.mymodule.internal to com.example.othermodule;
}
依赖模块(requires)
**requires**用于声明模块依赖。
module com.example.mymodule {
// 依赖其他模块
requires java.base; // 隐式依赖,可以省略
requires java.sql;
requires com.example.othermodule;
// 传递依赖
requires transitive com.example.common;
}
使用服务(uses)
**uses**用于声明使用的服务。
module com.example.mymodule {
uses com.example.service.MyService;
}
提供服务(provides ... with)
**provides**用于提供服务实现。
module com.example.mymodule {
provides com.example.service.MyService
with com.example.service.impl.MyServiceImpl;
}
打开包(opens)
**opens**用于开放包,允许反射访问。
module com.example.mymodule {
// 开放包给所有模块
opens com.example.mymodule.reflection;
// 开放包给特定模块
opens com.example.mymodule.reflection to com.example.othermodule;
}
模块依赖示例
示例 1:简单模块
模块 A(com.example.modulea):
// module-info.java
module com.example.modulea {
exports com.example.modulea.api;
}
// com/example/modulea/api/ServiceA.java
package com.example.modulea.api;
public class ServiceA {
public void doSomething() {
System.out.println("ServiceA 执行");
}
}
模块 B(com.example.moduleb):
// module-info.java
module com.example.moduleb {
requires com.example.modulea;
}
// com/example/moduleb/ClientB.java
package com.example.moduleb;
import com.example.modulea.api.ServiceA;
public class ClientB {
public void useService() {
ServiceA service = new ServiceA();
service.doSomething();
}
}
示例 2:传递依赖
模块 Common(com.example.common):
// module-info.java
module com.example.common {
exports com.example.common.util;
}
// com/example/common/util/Logger.java
package com.example.common.util;
public class Logger {
public void log(String message) {
System.out.println("日志:" + message);
}
}
模块 A(com.example.modulea):
// module-info.java
module com.example.modulea {
requires transitive com.example.common; // 传递依赖
exports com.example.modulea.api;
}
// com/example/modulea/api/ServiceA.java
package com.example.modulea.api;
import com.example.common.util.Logger;
public class ServiceA {
private Logger logger = new Logger();
public void doSomething() {
logger.log("ServiceA 执行");
}
}
模块 B(com.example.moduleb):
// module-info.java
module com.example.moduleb {
requires com.example.modulea;
// 不需要显式 requires com.example.common
// 因为 modulea 使用了 requires transitive
}
// com/example/moduleb/ClientB.java
package com.example.moduleb;
import com.example.modulea.api.ServiceA;
import com.example.common.util.Logger; // 可以直接使用
public class ClientB {
public void useService() {
ServiceA service = new ServiceA();
service.doSomething();
Logger logger = new Logger();
logger.log("ClientB 执行");
}
}