从 Java9 就引入了模块化的新语法了。如果我们想在项目中使用 Java9 及以上的版本的话,模块化是无法忽视的。它不像 Java8 的 lambda 表达式,我们可以不使用 lambda 这个新特性,仍然用老旧的 API 进行替代。但是模块化就不同。我们甚至发现,新的版本里, rt.jar 已经不存在了。JDK 的结构和基础库率先模块化了。
模块化 API
模块化的背景和概念本篇文章就不概述了,读者可以查看官方文档或者通过网上不错的博客进行了解。我们主要讲解一下 module-info.java 里的一些配置含义。
自定义的 helo.service 模块,包含了不少指令,我们分别进行介绍。
module helo.service {
exports com.maple.netty.handler;
exports com.maple.hello.service to hello.client;
requires slf4j.api;
requires io.netty.all;
requires gson;
requires hello.api;
requires hello.common;
uses com.google.gson.Gson;
opens com.maple.hello;
}
exports 和 exports to 指令
exports 指令用于指定一个模块中哪些包对外是可访问的。而 exports…to 指令则用来限定哪些模块可以访问当前模块导出的类,通过逗号分隔可以指定多个模块访问当前模块导出的类。这种方式称为限定导出(qualified export)。
require 指令
require 指令声明一个模块所依赖的其他模块,在 Java9 之后,我们除了引入 Jar 包依赖后,如果想要使用它们,还需要在 module-info.java中使用 require 声明使用。
uses 指令
uses 指令用于指定一个模块所使用的服务,使模块成为服务的消费者。其实就是指定一个模块下的某一个具体的类。
下面是 requires 和 uses 的 主要区别:
module hello.client {
requires gson;
uses com.google.gson.Gson;
}
provides…with 指令
该指令用于说明模块提供了某个服务的实现,因此模块也称为服务提供者。provides 后面跟接口名或抽象类名,与 uses 指令后的名称一致,with 后面跟实现类该接口或抽象类的类名。
例如java.base 模块里的其中一个声明,with后面为前者的一个实现类。
provides java.nio.file.spi.FileSystemProvider with jdk.internal.jrtfs.JrtFileSystemProvider;
open, opens, opens…to 指令
Java9 之前,Java 类的属性即使定义为 private 也是能够被访问到的,我们可以通过反射等手段达到目的。
Java9 模块化推出的一个重要目的就是强封装,可以完全的将不想暴露的类和属性给保护起来。
默认情况下,除非显式地导出或声明某个类为 public 类型,那么模块中的类对外部都是不可见的,模块化要求我们对外部模块以最小范围进行暴露。
open 等相关的指令目的就是来限制哪些类或者属性能够通过反射技术访问。
opens 指令
opens package 指定模块某个包下的所有 public 类都能被其他模块通过反射进行访问。
opens ... to 指令
opens package t