Java 9 最大的变化之一是引入了模块系统(Jigsaw 项目)。
模块是代码和数据的封装体。模块的代码被组织成多个包,每个包中包含Java类和接口;模块的数据则包括资源文件和其他静态信息。
模块系统的目标
更好的封装性
模块化系统允许开发者显式地定义哪些部分的代码对外可见,哪些部分是内部实现细节。通过 module-info.java 文件,模块可以声明哪些包是公开的,哪些包是隐藏的。这种封装性提高了代码的安全性和可维护性。
可靠的配置
模块化系统提供了一个更可靠的方式来定义模块之间的依赖关系。在 module-info.java 文件中,模块可以声明它们需要哪些其他模块,从而在编译时和运行时确保所有必要的依赖都存在。这避免了类路径下可能存在的版本冲突和缺失依赖的问题。
强制性服务加载
模块化系统允许模块声明和使用服务,服务提供者可以通过 provides 和 uses 关键字在 module-info.java 文件中进行声明,从而实现模块之间的解耦和动态加载。
更小的运行时环境
通过模块化系统,开发者可以创建包含最小运行时环境的定制 JRE。这样可以减少应用的内存占用和启动时间,特别适合于容器化和微服务架构。
示例
我们新建一个maven项目,有moduleA和moduleB两个模块。
在moduleA中,我们定义com.example.student和com.example.teacher两个包,然后分别创建Student和Teacher两个类。
package com.example.teacher;
public class Teacher {
public void teach() {
System.out.println("teach");
}
}
package com.example.student;
public class Student {
public void study() {
System.out.println("study");
}
}
然后在moduleA的src/main/java目录下创建module-info.java,通过exports com.example.student声明com.example.student包是公开的,可以被其他模块访问。只有被导出的包中的公共类和接口才能被其他模块使用。
module moduleA {
exports com.example.student;
}
然后在moduleB的src/main/java目录下创建module-info.java,通过requires moduleA声明当前模块依赖于moduleA,这会让编译器和运行时系统知道当前模块需要依赖的模块,以确保这些模块在编译和运行时都可用。
module moduleB {
requires moduleA;
}
然后我们在moduleB中新建Test类
package com.example.test;
import com.example.student.Student;
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.study();
}
}
执行main方法,命令行会打印study,但是在Test类中,我们无法引用Teacher类,因为teacher包没有被exports声明公开。
这是项目的整体结构,我们可以看到在Test类中无法引入Teacher类。
图1
下面贴出其它代码
moduleA的pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>module-test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>moduleA</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
moduleB的pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>module-test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>moduleB</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>moduleA</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
项目根目录pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>module-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
总结
通过这个简单的示例,展示了 moduleA 和 moduleB 两个模块是如何相互依赖和交互的。这样的设计展示了 Java 9 模块化系统如何增强代码的组织和管理,提升软件系统的可维护性和安全性。
网友评论