一、java模块化概述
1.传统的java开发
为什么引入模块化,因为jdk8以前开发模式都是传统的java开发:
- jar文件,压缩分发;
- package+public/protected/default/private机制
简介:
优点:
- 简单,适合中小型程序
缺点:
- 过于简单了,难以适应复杂的权限要求
- 程序员可以随意访问和控制代码
2.java模块化系统
2.1模块化的三个原则:
- 强封装性:一个模块必须能够对其他模块隐藏其部分代码
- 定义好良好的接口:模块必须向其他模块公开定义良好且稳定的接口
- 显式依赖:明确一个模块需要哪些模块的支持才能完成工作。
2.2java9引入新的模块化系统
Jigsaw拼图:
- 以模块(module)为中心
- 对jdk本身进行模块化
- 提供一个应用程序可以使用的模块系统
Jigsaw拼图的优点
二、模块的创建和运行
1.命令行方法创建:
文件结构:
操作步骤:
相关命令:
2.Eclipse创建:
文件结构:
操作步骤:
三、模块信息文件
文件命名为:module-info.java
模块命名:模块名称必须唯一,可以不和包名相同,使用有代表性的词语,不需要包括版本号。
常见操作:
requires:依赖其他模块
- requires调用其他的模块,调用多个模块则以逗号隔开就行。
- 但是单纯的requires依赖不会传递,以requires transitive关键调用则可以依赖传递
- java --list-modules查看系统提供的模块
- java --decribe-module看某一个模块
exports:输出给别人使用
- 只有输出了,其他的模块才能使用
- 可以指定某些包的输出
- 可以限定输出到特定的模块使用 exports<package>to<module1>,<module2>
open:将当前模块开放用于反射
- exports导出的包public部分可以反射,其他权限修饰的内容和未导出的部分无法反射
- opens可以打开一些包,其他模块可以反射调用这些包及内容
- open module打开整个模块
- 打开一个包 open <package>
- 仅对某些模块打开一个包:opens <package> to <module1>, <module2>
四、服务
- java模块系统引入服务功能,实现解耦
- 模块对外只暴露接口,隐藏实现类
- provides提供接口,with实现类
- uses消费接口
- ServiceLoader通过load加载接口的实现类
- 每一次load,默认情况下都会产生新的各自独享的实例,没有唯一的服务实例
- 可以调用reload刷新
两种创建服务实例的方法
1.服务实现类有public的无参构造函数
2.使用单独的静态提供者方法
实例:使用的为方法1:
package first.p1;
import java.util.ServiceLoader;
public interface Shoe {
public void walk();
// public static Iterable<A1> getA1()
// {
// return ServiceLoader.load(A1.class);
// }
}
package first.p2;
import first.p1.Shoe;
public class DoubleStar implements Shoe {
public void walk() {
System.out.println("DoubleStar is walking");
}
}
package first.p2;
import first.p1.Shoe;
public class Warrior implements Shoe {
public void walk() {
System.out.println("Warrior is walking");
}
}
module module.first {
exports first.p1;
provides first.p1.Shoe
with first.p2.DoubleStar,first.p2.Warrior;
}
module module.second {
requires module.first;
uses first.p1.Shoe;
}
package second.p1;
import java.util.ServiceLoader;
import first.p1.Shoe;
public class ShoeTest {
public static void main(String[] args)
{
Iterable<Shoe> objs = ServiceLoader.load(Shoe.class);
for(Shoe obj:objs)
{
obj.walk();
System.out.println(obj.hashCode());
}
//每次load,都产生新的实例
objs = ServiceLoader.load(Shoe.class);
for(Shoe obj:objs)
{
obj.walk();
System.out.println(obj.hashCode());
}
}
}
输出:
DoubleStar is walking
1504109395
Warrior is walking
1908316405
DoubleStar is walking
234698513
Warrior is walking
1121172875
补充:
总结:模块化很好,但是由于比较新所以还未做到支持性广泛,并且庞大的第三方库几乎都不是模块开发的,所以在程序巨大时可以尝试用模块化编程,一般还是采用传统模式。
参考中国大学mooc《java核心技术》