java 模块化基础
模块化概述
JDK8以前的开发模式:
- java源代码以java文件(类、接口、注解等)形式存在。
- 每一个java文件被放到一个指定的包中。
- 多个class文件组成的类库通常以jar包呈现。
- jar文件无法控制外界对其内部public类的访问。
- 等等。
模块化必须遵守的三个原则。
- 强封装性:一个模块必须能够对其他模块隐藏部分代码。
- 定义良好的接口:模块必须向其他模块公开定义良好且稳定的接口。
- 显示依赖:明确一个模块需要哪些模块的支持才能完成工作。
java 模块化系统:jigsaw(拼图)。
- 以模块(module)为中心。
- 对JDK本身进行模块化,提供一个应用程序可以使用的系统模块。
- 优点:可靠的配置(模块化配置资源),强封装性,可扩展性,安全性,性能优化。
java 模块化系统尚未成熟,目前各个开发工具支持力度不一致。且适用于大型项目。谨慎使用。
模块化创建
在eclipse中创建。
- 新建java project,可直接创建module-info.java(jdk9以上)。
或者在项目中邮件configure中的create module-info.java。 - 创建模块名称。
可以直接修改src为相应的模块名称,或者新建一个文件夹。 - 修改module-info.java文件。
- 编译,运行,打包操作。
如下图,这里在项目MOOC_NEW下创建了名为MOOC_NEW的mudule。且在MOOC_NEW模块下创建了3个包。包下创建对应的java文件。
在module-info.java中编写模块的配置。
模块信息文件(module-info.java)
- 模块安全连接的关键。
- 是与模块与外界沟通的桥梁。
- 模块名称必须唯一。
//模块名称MOOC_NEW
module MOOC_NEW {
//esports输出给别人使用。
exports cn.hello;
//需要的依赖。
requires MOOC_NEW1;
}
requires调用其他模块。
- java --list-modules:查看jdk提供的模块。
- java --describe-module 看具体某一模块。
- requires可以添加多个模块,中间以逗号隔开。
- 采用requires transitive N,编译和运行时都传递依赖N。
- requires static N,编译依赖N,运行可选。
- requires transitive static N,编译传递依赖,运行时可选。
exports 将当前模块输出。
只有输出,别人才可以使用,否则别人连采用反射的机会都没有。
- exports <package>,指定输出哪些包。
- exports <package> to<module1>, <module1>; 限定输出到某些模块。
opens 将当前模块开放用于反射。
- exports导出的包可以用于反射。
- opens可以打开一些包用于反射。
- open module 某块名称,打开整个模块。
- opens <package>,打开一个包。
- opens <package> to <module1>, <module2>; 仅对某些模块打开一个包。
服务
- java模块系统引入新功能,实现解耦。
- 模块对外只暴露接口,隐藏实现类。
- provides提供接口,with实现类(不导出)。
- uses消费接口。
- ServiceLoader加载接口的实现类。
如:在模块MOOC_NEW的module-info.java中:
module MOOC_NEW {
exports first.p1;
provides first.p1.Shoe
with first.p2.Nike;
}
在模块MOOC_NEW1的module-info.java中:
module MOOC_NEW1 {
requires MOOC_NEW;
uses first.p1.Shoe;
}
在模块MOOC_NEW中,定义了接口Shoe及其实现类。分别位于first.p1和first.p2中。
在模块MOOC_NEW1中的second.p1包中,编写测试文件如下:
package second.p1;
import java.util.ServiceLoader;
import first.p1.Shoe;
public class ShoeTest {
public static void main(String[] args) {
ServiceLoader<Shoe> objs = ServiceLoader.load(Shoe.class);
for(Shoe obj : objs) {
obj.wolk();
}
}
}
-
ServiceLoader通过load加载接口的实现类(with语句提供)。
-
每次load,都会产生新的各自的对象。
-
可以调用reload进行刷新。
-
java 模块系统提供两种方法创建服务实例。
- 服务实现类有public的无参构造函数。
- 使用单独的静态提供者方法。
– 一个名为provider的public static无参数方法。
– 返回服务接口或者子类。
如,在模块MOOC_NEW下的包first.p1下创建一个类shoeFactory。
public class shoeFactory{
public static Shoe provider(){
Shoe shoe = new Nike();
return shoe;
}
}
并将模块MOOK_NEW的module-info.java文件改为:
module MOOC_NEW{
exports first.p1;
provider first.p1.Shoe
with first.p1.shoeFactory;
}