Java 9模块化编程!
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
Java 9引入了模块化系统(Project Jigsaw),旨在改善Java应用的可维护性、性能和安全性。模块化允许开发者将代码划分为不同的模块,模块之间可以明确声明依赖关系,从而实现更好的封装、重用和管理。在这一新特性中,JDK自身也被模块化,允许开发者根据需要构建定制化的JRE。本文将介绍Java 9模块化的引入与概念、模块定义与模块路径、模块之间的依赖关系以及如何使用JLink工具构建自定义JRE。
1. Java 9模块化的引入与概念
模块化编程的背景
Java一直是一个面向对象的编程语言,随着时间的推移,应用程序的规模变得越来越庞大,代码的维护、性能和安全性成为了不可忽视的问题。为了改善这些问题,Java 9引入了模块化系统(Project Jigsaw),通过模块化将应用程序划分为多个模块,使得模块间的依赖关系变得清晰,并能够按需加载和优化应用程序的运行时环境。
什么是模块?
在Java 9之前,Java应用程序的组织方式主要是通过包(Package)和类(Class)来实现的。而Java 9引入的模块化机制将Java代码组织成模块(Module),每个模块可以包含类、接口、枚举等类型的成员。模块通过module-info.java
文件进行定义,模块之间的依赖关系也通过该文件声明。
模块的优势
- 封装:模块化让代码更加模块化和封装,限制了模块外部对内部实现的访问。
- 依赖管理:通过明确的依赖声明,减少了不同模块之间的耦合度。
- 性能优化:通过模块化,可以根据应用需求构建自定义JRE,剔除不必要的部分,从而提高性能和减小JRE的体积。
- 安全性:模块化可以增强应用程序的安全性,明确模块间的访问权限。
2. 模块定义与模块路径
定义模块
模块的定义通过一个特殊的module-info.java
文件来实现。该文件位于模块的根目录,并用于描述模块的名称、依赖关系以及对外暴露的包。模块文件的基本语法如下:
module com.example.myModule {
// 模块依赖的其他模块
requires java.base; // Java标准库的基础模块(java.base是默认包含的)
// 模块导出的包
exports com.example.myModule.package1;
exports com.example.myModule.package2;
// 模块需要的服务或功能
uses com.example.myModule.Service;
provides com.example.myModule.Service with com.example.myModule.ServiceImpl;
}
module
:定义模块的名称,模块名称应该是唯一的。requires
:声明该模块依赖的其他模块。exports
:声明该模块对外暴露的包,其他模块可以通过这些包来访问模块中的类。uses
:声明该模块使用的服务接口。provides
:声明该模块提供的服务接口及其实现。
模块路径
Java 9引入了模块路径(Module Path),它用于替代类路径(Classpath)来指定模块的存储位置。模块路径中的每个模块都是一个独立的文件夹,包含module-info.java
文件以及该模块的其他类文件。
-
编译模块:使用
--module-source-path
参数指定模块的源代码路径。javac --module-source-path src -d out $(find src -name "*.java")
-
运行模块:使用
--module-path
参数指定模块路径。java --module-path out -m com.example.myModule/com.example.myModule.Main
3. 模块之间的依赖关系
模块依赖
在Java 9的模块化系统中,模块之间的依赖关系是显式声明的,通过requires
关键字指定。例如,模块A
可能依赖模块B
,则模块A
的module-info.java
文件中应包含:
module A {
requires B;
}
-
requires
:定义当前模块依赖的其他模块,编译和运行时需要这些模块。可以指定transitive
(继承依赖)来自动传递依赖给其他模块。module A { requires transitive B; // B也会成为A的使用者 }
-
requires static
:定义静态依赖,仅在编译时有效,但在运行时不会被加载。module A { requires static B; }
-
模块的版本:可以指定模块的版本约束,确保某个模块的版本符合需求。
module A { requires B version "1.2.0"; }
访问控制
模块化系统通过exports
来控制模块内部的类和包是否对外可见。通过这种方式,可以有效地实现模块的封装和访问控制。仅在module-info.java
中声明了exports
的包,其他模块才能访问。
-
exports
:声明模块对外暴露的包。module A { exports com.example.myPackage; }
-
访问限制:模块可以通过
opens
关键字动态暴露包给反射机制使用。例如,JUnit测试框架需要访问私有成员时,可以使用opens
。module A { opens com.example.myPackage to junit; }
4. JLink工具与自定义JRE构建
JLink工具
JLink
是Java 9引入的一个新工具,用于根据特定的需求构建自定义的JRE。它允许开发者选择性地将应用程序需要的模块打包到一个最小的JRE中,从而减少JRE的体积,提高启动性能。
使用JLink构建自定义JRE
-
安装JDK和构建模块:首先,需要使用
javac
编译应用程序的模块,并创建模块路径。javac --module-source-path src -d out $(find src -name "*.java")
-
使用JLink创建自定义JRE:使用JLink命令,将应用程序的模块和依赖模块打包成一个自定义的JRE。
jlink --module-path $JAVA_HOME/jmods:out --add-modules com.example.myModule --output my-jre
--module-path
:指定包含JDK模块和自定义模块的路径。--add-modules
:指定要包含在自定义JRE中的模块。--output
:指定输出目录,my-jre
将是包含自定义JRE的目录。
-
运行自定义JRE:创建的自定义JRE可以直接用于运行应用程序。
my-jre/bin/java -m com.example.myModule/com.example.myModule.Main
通过JLink
,你可以创建一个仅包含应用程序所需模块的JRE,减少了JRE的大小,提高了启动速度。
JRE的优势
- 减小体积:通过只包含必需的模块,定制化的JRE可以显著减少JRE的大小。
- 提高性能:减少不必要的模块和文件,提高应用程序的加载速度。
- 安全性:通过剔除不必要的模块,减少潜在的安全风险。
总结
Java 9的模块化系统为开发者提供了更加灵活、可扩展的应用程序架构设计方式。通过显式地定义模块、模块之间的依赖关系以及访问控制,模块化能够使得代码更清晰、更易维护。JLink
工具的引入使得开发者可以根据具体需求构建一个精简的JRE,从而提高应用程序的性能和安全性。掌握Java 9模块化的使用,可以帮助开发者更好地组织和优化Java应用程序。
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!
- 点赞
- 收藏
- 关注作者
评论(0)