Java 平台模块系统 (JPMS) 代表了 Java 平台自诞生以来最重要的架构变化之一。作为一个广泛使用 Java 应用程序的人,我亲眼目睹了这个强大的功能如何改变了我们构建和组织代码的方式。
Java 9 中引入的模块系统提供了一种在比包更高级别组织代码的基本方法。从本质上讲,模块是一个独立的单元,它显式声明其依赖项以及它对其他模块可用的内容[1]。这是对传统的基于类路径的方法的革命性改变,在传统的基于类路径的方法中,所有代码基本上都可以被其他所有代码访问。
让我们从基本的模块声明开始:
module com.myapp.core { requires java.base; exports com.myapp.core.api; provides com.myapp.core.spi.Service with com.myapp.core.impl.ServiceImpl; }
这个简单的声明封装了几个关键概念:模块命名、依赖声明和包导出[2]。模块系统在编译时和运行时强制执行这些边界,提供比以前更强的封装。
创建模块化应用程序时,结构通常如下所示:
myapp/ ├── src/ │ ├── module-info.java │ └── com/ │ └── myapp/ │ └── Main.java └── out/
这是一个简单的模块化应用程序的完整示例:
// module-info.java module com.myapp { requires java.logging; exports com.myapp.api; } // com/myapp/api/Service.java package com.myapp.api; public interface Service { String getMessage(); } // com/myapp/internal/ServiceImpl.java package com.myapp.internal; import com.myapp.api.Service; public class ServiceImpl implements Service { public String getMessage() { return "Hello from modular service!"; } }
JPMS 最强大的功能之一是其强大的封装机制[4]。与传统的公共/私有访问修饰符不同,模块级封装会阻止访问内部实现细节,即使它们被标记为公共。
考虑这个场景:
module com.myapp.core { exports com.myapp.core.api; // Internal packages are not exported // com.myapp.core.internal remains hidden }
即使内部包中的类是公共的,除非显式导出,否则无法从模块外部访问它们[1]。与前模块 Java 相比,这代表了封装性的显着改进。
JPMS 通过 require 指令引入显式依赖声明。这有助于防止经常困扰 Java 应用程序的“JAR 地狱”问题[3]。以下是通常管理依赖关系的方式:
module com.myapp.service { requires com.myapp.core; requires java.sql; requires transitive com.myapp.common; }
requires 传递指令特别有趣,因为它允许依赖转发,使所需的模块可用于任何依赖于此的模块[2]。
模块系统与Java的ServiceLoader机制完美集成:
module com.myapp.core { uses com.myapp.spi.Plugin; } module com.myapp.plugin { provides com.myapp.spi.Plugin with com.myapp.plugin.impl.PluginImpl; }
这在服务接口和实现之间创建了清晰的分离,从而实现了真正的插件架构[8]。
将现有应用程序迁移到 JPMS 可能具有挑战性。最常见的问题包括:
module com.myapp.core { requires java.base; exports com.myapp.core.api; provides com.myapp.core.spi.Service with com.myapp.core.impl.ServiceImpl; }
为了帮助迁移,Java 提供了 --add-exports 和 --add-opens 命令行选项[5]:
myapp/ ├── src/ │ ├── module-info.java │ └── com/ │ └── myapp/ │ └── Main.java └── out/
模块系统通过以下方式实现更好的运行时优化:
您可以使用 jlink 创建自定义运行时映像:
// module-info.java module com.myapp { requires java.logging; exports com.myapp.api; } // com/myapp/api/Service.java package com.myapp.api; public interface Service { String getMessage(); } // com/myapp/internal/ServiceImpl.java package com.myapp.internal; import com.myapp.api.Service; public class ServiceImpl implements Service { public String getMessage() { return "Hello from modular service!"; } }
测试需要特别考虑。这是典型的测试模块设置:
module com.myapp.core { exports com.myapp.core.api; // Internal packages are not exported // com.myapp.core.internal remains hidden }
许多构建工具为测试模块化应用程序提供特定支持。例如,Maven 使用带有适当配置的 maven-surefire-plugin [8]。
让我们看一个更完整的模块化应用程序示例:
module com.myapp.service { requires com.myapp.core; requires java.sql; requires transitive com.myapp.common; }
这种结构创建了清晰的关注点分离,同时保持强大的封装和显式依赖关系[11]。
模块系统从根本上改变了我们构建 Java 应用程序的方式。虽然过渡可能具有挑战性,特别是对于现有应用程序而言,但可维护性、安全性和性能方面的好处使其值得。随着生态系统的不断成熟,我们看到越来越多的库和框架采用 JPMS,从而更轻松地构建真正的模块化应用程序。
Java 开发的未来是模块化的,掌握 JPMS 对于 Java 开发人员来说变得越来越重要。无论您是开始一个新项目还是维护现有项目,理解这些概念都将帮助您构建更强大且可维护的应用程序。
有关更多此类见解和故事,请访问我们的 https://techkoalainsights.com/
一定要鼓掌和关注我 TechKoala Insights 了解更多这样的故事
投资者中心 |智能生活 |
时代与回响 |
令人费解的谜团 |
印度教 |
精英开发 |
JS学校
以上是Java 模块的释放:超安全、快如闪电的应用程序背后的秘密武器的详细内容。更多信息请关注PHP中文网其他相关文章!