JAVA 9 的模块化
TOC
[TOC]
模块化前时代
- Ant 时代(时代比较老)
- Maven 时代(Gradle)
- OSGI 时代 (
没用过)
Ant
javac
命令,Java 早就有了,
1
2
3
4
5
<!--... -->
<target>
<delete dir="${file}"/>
</target>
<!--... -->
主要进行了文件操作。
Maven
- 文件管理
<resource>
- 版本管理
<dependency>
,GAV
帮我们确定一个版本。dependencyManagement
缺点
- 编译时进行处理的,运行时加载的一些类,
OSGI
- http://enroute.osgi.org
运行时操作的
OSGI 并不比 模块化特别差。
Eclipse 就是基于 OSGI 来构建的。
Spring 也支持过 OSGI,动态模块化,OSGI 反而把问题搞复杂了,间接依赖很难去把控
加载的时候,文件系统不一定加载具体某个版本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+--------------+ +--------------+
| ObjectUtils | | StringUtils |
+--------------+ +--------------+
| |
| |
+-----------------+-----------------+
|
+------------------------+------------------------------+ 文件系统
| | |
| +-------------—-+----------+ |
| | | |
| +------------------+ +------------------+ |
| | commons-lang 2.4 | | commons-lang 2.6 | |
| +------------------+ +------------------+ |
| |
+-------------------------------------------------------+
文件系统加载的不确定性,#list(File)
加载的不确定性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
+--------------+
| Tomcat |
+--------------+
|
Tomcat/lib
|
+---------------+
| ClassLoader |
| Commons |
+---------------+
|
+-------------------+---------------------+
| |
+-------------+ +-------------+
| App1 | | App1 |
+-------------+ +-------------+
| |
WEB-INF/lib WEB-INF/lib
| |
+---------------+ +---------------+
| ClassLoader1 | | ClassLoader1 |
+---------------+ +---------------+
| |
| |
+---------------+ +---------------+
| ClassLoader1 | | ClassLoader1 |
+---------------+ +---------------+
~app1/WEB-INF/ ~app1/WEB-INF/
lib/commons-lang-2.4.jar lib/commons-lang-2.5.jar
Tomcat 有 自己的 Commons
我们启动程序有一个 -classpath
环境变量,会导致另一个事情,没有办法区分。
在本地环境可以,在线上部署的时候不可以的时候,
ClassLoader
- Tomcat 有一个
WebAppClassLoader
extendsURLClassLoader
在 -classpath
里边的时候就是先来先服务,主要就是一位内 URLClassLoader
的 addURL
方法。
URLClassLoader#findClass
- 就是
getResource
的方法,先来先服务。通过类文件去寻找。return defineClass(className)
如果可以清楚的知道我 jar 包的版本
NoSuchMethodException
模块化
- 模块声明
- module
com.darian{}
- 依赖
- requires
- 导出
- exports
- module
1
2
D:\anzhuanga\Java\jdk-11.0.1\bin\java.exe "-javaagent:D:\anzhuang\IntelliJ IDEA 2020.1\lib\idea_rt.jar=6529:D:\anzhuang\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -p D:\GitHub_Repositories\mercyblitz-gp-public\java9-modular-demo\out\production\java9-modular-demo -m com.darian/helloworld.com.darian.java9.helloWorld.HelloWorldMain
Hello, World
-m
-p
- module-path
没有了 classpath,一直跟到了 module-info
路径下边,
问题
模块不是想要什么就有什么。
如果把 module
删了的化,还是想用啥用啥。
1
2
3
4
module com.darian {
requires java.logging;
requires java.management;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***
*
*
* @author <a href="mailto:[email protected]">Darian</a>
* @date 2020/5/28 9:16
*/
public class HelloWorldMain {
public static void main(String[] args) {
Logger logger = Logger.getLogger(HelloWorldMain.class.getName());
logger.info("xxx");
System.out.println("Hello, World");
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
System.out.println(runtimeMXBean.getUptime());
}
}
优点
- 就是我们按需引入就好了
缺点
- 就是我们不许知道在 类在哪里。
运行时,只需要运行我的 jar 包就更小了,就会容量变得更加的小。
- 它还可以显示的帮我做隔离,
另一个目录下 可以引入另一个模块。
- Java 的另一个程序支持,引入就可以
定义模块
- 模块结构
- 模块描述文件
- module-info.class
- Java 平台模块
在 模块化里边,并没有了 public
的类。
必须显示的 exports
,支队本模块来 可读性
启动的时候,会更加的小。
Maven 的使用就发生了变化。
使用模块
- 模块路径
- 模块解析
- 模块可读性
- 模块访问性
- 隐形可读性
变化
-module-path
取代了class-path
1
2
3
4
5
module user.domain {
exports com.darian.domain;
// 不需要依赖其他模块
}
1
2
3
4
5
6
7
8
9
10
11
12
module user.service {
// transitive 传递依赖
requires transitive user.domain;
requires java.logging;
// 导出
// 1. 本模块的 public class 需要显示的 exports
// 2. exports 不支持子包传递
exports com.darian.service;
exports com.darian.service.impl;
}
1
2
3
4
module bootstrap {
requires user.service;
}
你可以传递依赖过来。
-
传递依赖会特别麻烦。
-
没有增加复杂度,只是增加了透明度。
高端玩家的游戏
JAVA 9 是 -claspath
和 -module-path
混用。
工具整合
- Maven
- IDE
- Idea
兼容性
- 非命名模块
- 自动模块
1
2
3
D:\anzhuanga\Java\jdk-11.0.1\bin\java.exe "-javaagent:D:\anzhuang\IntelliJ IDEA 2020.1\lib\idea_rt.jar=8021:D:\anzhuang\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -p D:\GitHub_Repositories\mercyblitz-gp-public\java9-module-demo\bootstrap\target\classes;D:\GitHub_Repositories\mercyblitz-gp-public\java9-module-demo\user-service\target\classes;D:\GitHub_Repositories\mercyblitz-gp-public\java9-module-demo\user\target\classes;
...
Java 9 以后通过,-p
引入
就是 module-path
和 class-path
类似,
它即使可以帮你把这个东西搞进来,但是它还是无法预判你用到了哪些东西
你看不出来一个很明显的提升
https://openjdk.java.net/projects/jigsaw/spec/sotms
使用场景
- 当你场景受限,需要直系依赖的时候就有用了。
Spring 的使用
spring.io
工程。- https://spring.io/projects/platform#learn
spring-io-platform
帮你做到了版本管理,- 而我们用模块化的时候,当工具做的更好的时候,可能使用的更加顺手
- https://spring.io/projects/platform#learn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ java --list-modules
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]