美文网首页
Java模块系统入门(一)

Java模块系统入门(一)

作者: 耿耿不寐如有隐忧 | 来源:发表于2019-07-22 00:09 被阅读0次

0. 模块是什么

         Java Platform Module System(Java平台模块系统).是在Java 9 中引入的一个模块化组件.

0.1 逻辑关系

         模块系统 最直观的例子就是官方API文档结构发生的变化(所有内容以java11为例):


API文档首层结构-模块.png

         首先看到的就是module列表, 而不是原来的package列表. 点击进入java.base这个module, 看到的才是熟悉的package列表. 甚至在这些页面中,还会带有模块之间的依赖关系图.

java.base模块中的包.png
java.sql模块依赖关系图.png

         逻辑上讲, 是用来组织类和接口的, 而模块就是用来组织的, 模块在包的外层又添加了一层封装.

0.2 物理结构

         物理结构上, 类和接口是文件, 包是层级目录, 指定包名的文件放入相应的目录. 而模块则是在包的外层又添加了一层目录,作为模块的根目录, 并在根目录下放置模块文件module-info.java, 以java.sql为例:

java.sql模块目录结构
         可以看到java.sql这个模块的底下有两个package: java.sqljavax.sql, 都是层级目录结构. 而模块根目录java.sql的命名规范虽跟package相同,但是并不是层级目录而只是一个普通的目录.
         java.sql模块根目录下的module-info.java内容:
module java.sql {
    requires transitive java.logging;
    requires transitive java.transaction.xa;
    requires transitive java.xml;

    exports java.sql;
    exports javax.sql;

    uses java.sql.Driver;
}

  • requires 表示该模块依赖的其他模块
  • exports 表示该模块对外公开的包, 这也是模块的重要作用之一, 控制其他模块对该模块的包的访问.

1. 自己写一个无用模块

         既然知道了他的逻辑关系和物理结构, 就可以模仿它去实现自己的module了.

1.1 创建项目目录

项目目录结构.png
  • MyModules: 项目目录
  • src: 源码目录
  • src/com.my.firstmodule: 模块根目录
  • mods: 存放编译的class文件
  • target: 存放打包的jar文件
  • module-info.java: 模块文件

1.2 编写代码

//MyFirstModule.java
package com.my.firstmodule;

public class MyFirstModule {
    public static void main(String[] args) {
    System.out.println("my first module!");
    }
}


//module-info.java
module com.my.firstmodule {
    requires java.base;
}

         module-info.java 只是声明了所依赖的java.base模块. 事实上可以省略对 java.base的依赖声明.

1.3 编译模块

在项目根目录下执行javac

 javac -d mods/com.my.firstmodule src/com.my.firstmodule/module-info.java src/com.my.firstmodule/com/my/firstmodule/MyFirstModule.java 

-d 选项指定编译的类文件输入目录, 后面跟着需要编译的源文件.编译后的目录结构

MyModules/
├── mods
│   └── com.my.firstmodule
│       ├── com
│       │   └── my
│       │       └── firstmodule
│       │           └── MyFirstModule.class
│       └── module-info.class
├── src
│   └── com.my.firstmodule
│       ├── com
│       │   └── my
│       │       └── firstmodule
│       │           └── MyFirstModule.java
│       └── module-info.java
└── target

1.4 运行模块

java --module-path mods --module com.my.firstmodule/com.my.firstmodule.MyFirstModule

运行结果: my first module!

1.5 打包模块

jar -c -f target/myfirstmodule-1.0.jar -e com.my.firstmodule.MyFirstModule -C mods/com.my.firstmodule .

在target目录下生成了jar文件

─ target
    └── myfirstmodule-1.0.jar

运行jar文件

java --module-path target/myfirstmodule-1.0.jar --module com.my.firstmodule/com.my.firstmodule.MyFirstModule

运行结果: my first module!

         我们的第一个简单的模块已经完成并运行成功了! 可喜可贺!可喜可贺! 但是感觉上命令行中写的更复杂了, 那为什么有了package之后还要引入module呢?

3. 为什么要引入模块系统

         在传统的面向对象设计中, 模块化的机制在Java语言中是由package提供的. 那为什么要再添加Module概念, 让事情更加复杂呢?
         这方面的描述在 JSR-376中, 有以下几点:

  • 可靠配置(Reliable configuration):
             classpath不能表示组件之间的关系, 所以如果有依赖的组件缺失, 只能在尝试使用它的时候才能发现. classpath允许从不同组件加载相同包的类, 导致无法预测的行为和难以侦测的错误.
             模块系统可以声明组件之间的依赖关系

  • 强封装(Strong encapsulation)
             Java语言和虚拟机没有提供一种机制, 让组件禁止其他组件访问自己的内部package. 所以只要是public的package, 外部组件是可以随意访问的.
             模块系统则可以声明哪些包可以被访问, 那些包不能被访问.
    java没有提供组织其他组件访问某个组件的内部包(package)
    jPM允许某个组件可以声明哪些包可以被访问.哪些包不可以.

  • 可扩展的平台(A scalable platform)
             JVM和JRE在尺寸上不断增大, 使得很多小设备很难运行JVM或者java应用.
             JavaSE本身使用模块系统分解后, 应用可以按需定制, 通过配置, 只包含自己需要的功能模块, 从而缩小应用尺寸.
             这一点可能是java在物联网时代抓住发展机遇的必备条件.

  • 更好的平台完整性(Greater platform integrity)
             随意的访问平台内部的API, 既不安全也会增加维护成本. 模块系统提供的强封装可以保证内JavaSE平台内部API不被访问.

  • 更高的性能(Improved performance)
             许多事先的, 整体程序优化技术, 如果能确定类引用的是某几个特定组件中的类, 而非运行时加载的任意类, 会更有效果. 程序性能尤其在应用组件同平台组件联合优化时增强.

现在还没听说哪个大型软件组织使用模块系统. 虽然大多数语言都有module这个概念, 但引入java中到底能不能带来非常大的好的转变还需要时间验证.理论总是需要实践检验的.

4. 文章推荐

Java 9 Modules(Part 1)
Java 9 Modules(Part 2)
Java 9 Modules(Part 3)
JSR-376

相关文章

网友评论

      本文标题:Java模块系统入门(一)

      本文链接:https://www.haomeiwen.com/subject/hklplctx.html