SpringBoot学习系列-jar包启动原理

打包生成两个jar包
ssmdemo-plus.jar 引入了相关第三方依赖。
ssmdemo-plus.jar.original 仅包含应用编译后的本地资源
 
jar包的目录结构
|—— BOOT-INF
  |—— classes  存放的是应用编译后的class文件
  |—— lib    存放的是应用依赖的第三方jar包文件
|——META-INF    存放应用打包信息maven坐标、pom文件和MANIFEST.MF
    |—— MANIFEST.MF
  |—— maven
|—— org  目录存放SpringBoot相关class文件
  |—— springframework

使用java -jar命令执行 spring Boot 应用的可执行jar文件
会读取META-INF/MANIFEST.MF文件的Main-Class属性值,该值表示应用程序执行入口类
MANIFEST.MF文件内容
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: NB-20200504-3
Start-Class: com.zwh.Application
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.2.3.RELEASE
Created-By: Apache Maven 3.6.1
Build-Jdk: 1.8.0_231
Main-Class: org.springframework.boot.loader.JarLauncher
会执行org.springframework.boot.loader包下的JarLauncher的main方法
这里会做操作
JarLauncher.java
public static void main(String[] args) throws Exception {
    (new JarLauncher()).launch(args);
}


Launcher.java
protected void launch(String[] args) throws Exception {
    JarFile.registerUrlProtocolHandler();
    ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
    this.launch(args, this.getMainClass(), classLoader);
}

JarFile.registerUrlProtocolHandler(); 

这个方法作用:

利用java url协议实现扩展原理,自定义jar协议
将org.springframework.boot.loader包 追加到java系统 属性java.protocol.handler.pkgs中,实现自定义jar协议

参考链接:java 自定义通讯协议 [https://blog.csdn.net/d_x_program/article/details/75038200]
java会在java.protocol.handler.pkgs系统属性指定的包中查找与协议同名的子包和名为Handler的类,
即负责处理当前协议的URLStreamHandler实现类必须在 <包名>.<协议名定义的包> 中,并且类名称必须为Handler
例如:
org.springframework.boot.loader.jar.Handler这个类 将用于处理jar协议

这个jar协议实现作用:
参考链接:SpringBoot FatJar启动原理 [https://www.cnblogs.com/jfire/p/11973093.html]
springBoot在打包时候会将第三方依赖jar包打进最终的Jar,变成一个可运行的FatJar。
默认情况下,JDK提供的ClassLoader只能识别jar中的class文件以及加载classpath下的其他jar包中的class文件。
对于jar包中的jar包是无法加载的
所以spring boot 自己定义了一套URLStreamHandler实现类和JarURLConnection实现类,用来加载jar包中的jar包的class类文件

 

下一步
ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
创建类加载器,得到可以加载嵌套式的jar文件的类加载器
 
然后
调用this.launch(args, this.getMainClass(), classLoader);方法,
读取Manifest的Start-Class属性利用反射执行main方法完成应用程序的启动
start-class属性其实就是我们项目里面的Application程序

 

posted @ 2020-06-10 19:43  海绵般汲取  阅读(1704)  评论(0编辑  收藏  举报