深入解析Java模块系统:Root Modules与Java EE的融合之道
在Java 9中,模块系统引入了一种新的编程范式,使得代码的组织和依赖管理更加清晰。本文将详细探讨Root Modules的概念,以及如何在Java 9中继续使用Java EE库,例如JAXB。
Root Modules概述
Root Modules是JDK 9中引入的一个概念,它们只包含module-info.java
文件,不包含任何包或Java代码。这些模块的主要作用是依赖其他模块,并使它们对外可见。java.se
就是这样一个模块,下面我们看看它的声明方式:
module java.se {
requires transitive java.compiler;
requires transitive java.datatransfer;
// 其他依赖省略...
}
'requires transitive’子句解析
transitive
关键字的效果是,目标模块不仅被当前模块(例如java.se
)所依赖,而且对依赖当前模块的其他模块也是可见的。例如requires transitive java.logging
将使得java.logging
对依赖java.se
模块的模块可见。这与exports
不同,exports
用于使包可见,而requires transitive
用于使导入的模块对外可见。
Root Modules的使用
当编译或加载未命名模块时,应该能够访问一组Root Modules中的一个,以便非模块化应用程序能够继续工作。默认的Root Modules集合是实现特定的。在JDK实现中,它是模块java.se
。如果我们使用一个不在默认Root Modules集合中的模块中的类会怎样呢?让我们通过一个例子来了解。
实例分析
以下示例使用JAXB API将字符串反序列化为对象:
public class MsgUnMarshaller {
public static void main(String... st) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(MsgObj.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader("<msgObj><msg>test msg</msg></msgObj>");
MsgObj msgObj = (MsgObj) unmarshaller.unmarshal(reader);
System.out.println(msgObj);
}
}
@XmlRootElement
public class MsgObj {
private String msg;
// getter和setter方法省略...
}
在尝试编译上述代码时,我们遇到了错误,因为JAXB相关的类对我们的未命名模块不可见。原因是java.se
中的默认Root Modules没有包含requires transitive java.xml.bind
。为了解决异常,我们需要使用--add-modules java.xml.bind
来添加模块。
编译与运行
使用以下命令编译和运行程序:
javac --add-modules java.xml.bind -d out src/com/logicbig/MsgObj.java src/com/logicbig/MsgUnMarshaller.java
java --add-modules java.xml.bind -cp out com.logicbig.MsgUnMarshaller
Java 9之前的情况
在Java 9之前,JAXB API和其他Java EE API自Java SE 6以来就捆绑在Java SE中,无需额外配置即可工作。Java 9决定通过新的模块系统将这些Java EE API从Java SE中分离出来,以减小JRE的大小,使其能够在更小的设备上运行。
java.se.ee模块
如果你的应用程序使用了大量的Java EE API,它在Java 9中运行时可能会失败。例如,如果你在应用程序中使用了JPA/Hibernate,它在编译和运行时可能会失败。与其逐个找出所需的模块,不如使用java.se.ee module
中声明的Java SE和Java EE模块的混合集。我们可以通过--add-modules
选项启用这组Root Modules。
在IDE中设置–add-modules选项
所有IDE都有设置编译器和JVM运行时选项的功能。例如,在IntelliJ中,我们可以如下设置它们:
示例项目
使用的技术与依赖:
- JDK 9