精尽Spring Boot源码分析 - Jar 包的启动实现

本文详细探讨了Spring Boot应用如何通过Maven插件打包成jar,并解释了jar包内部结构,如BOOT-INF目录和MANIFEST.MF文件的作用。文章深入分析了Spring Boot的JarLauncher类和自定义ClassLoader如何加载和启动应用,包括获取启动类、注册URL协议处理器、解析ClassPathArchives等步骤,揭示了Spring Boot jar包启动的秘密。
摘要由CSDN通过智能技术生成

概述

Spring Boot 提供了 Maven 插件 spring-boot-maven-plugin,可以很方便的将我们的 Spring Boot 项目打成 jar 包或者 war 包。

考虑到部署的便利性,我们绝大多数(99.99%)的场景下,都会选择打成 jar 包,这样一来,我们就无需将项目部署于 Tomcat、Jetty 等 Servlet 容器中。

那么,通过 Spring Boot 插件生成的 jar 包是如何运行,并启动 Spring Boot 应用的呢?这个就是本文的目的,我们一起来弄懂 Spring Boot jar 包的运行原理

这里,我通过 Spring Boot Maven Plugin 生成了一个 jar 包,其里面的结构如下所示:

  1. BOOT-INF 目录,里面保存了我们自己 Spring Boot 项目编译后的所有文件,其中 classes 目录下面就是编译后的 .class 文件,包括项目中的配置文件等,lib 目录下就是我们引入的第三方依赖
  2. META-INF 目录,通过 MANIFEST.MF 文件提供 jar 包的元数据,声明 jar 的启动类等信息。每个 Java jar 包应该是都有这个文件的,参考 Oracle 官方对于 jar 的说明,里面有一个 Main-Class 配置用于指定启动类
  3. org.springframework.boot.loader 目录,也就是 Spring Boot 的 spring-boot-loader 工具模块,它就是 java -jar xxx.jar 启动 Spring Boot 项目的秘密所在,上面的 Main-Class 指定的就是该工具模块中的一个类
  4. https://www.jianshu.com/p/b04a54873f3b

MANIFEST.MF

META-INF/MANIFEST.MF 文件如下:

 

Manifest-Version: 1.0 Implementation-Title: spring-boot-study Implementation-Version: 1.0.0-SNAPSHOT Built-By: jingping Implementation-Vendor-Id: org.springframework.boot.demo Spring-Boot-Version: 2.0.3.RELEASE Main-Class: org.springframework.boot.loader.JarLauncher # spring-boot-loader 中的启动类 Start-Class: org.springframework.boot.demo.Application # 你的 Spring Boot 项目中的启动类 Spring-Boot-Classes: BOOT-INF/classes/ # 你的 Spring Boot 项目编译后的 .class 文件所在目录 Spring-Boot-Lib: BOOT-INF/lib/ # 你的 Spring Boot 项目所引入的第三方依赖所在目录 Created-By: Apache Maven 3.6.3 Build-Jdk: 1.8.0_251 Implementation-URL: https://projects.spring.io/spring-boot/#/spring-boot-starter-parent/info-dependencies/dwzq-info/info-stock-project/sp-provider

参考 Oracle 官方对该的说明:

  • Main-Class:Java 规定的 jar 包的启动类,这里设置为 spring-boot-loader 项目的 JarLauncher 类,进行 Spring Boot 应用的启动
  • Start-Class:Spring Boot 规定的启动类,这里通过 Spring Boot Maven Plugin 插件打包时,会设置为我们定义的 Application 启动类

为什么不直接将我们的 Application 启动类设置为 Main-Class 启动呢?

因为通过 Spring Boot Maven Plugin 插件打包后的 jar 包,我们的 .class 文件在 BOOT-INF/classes/ 目录下,在 Java 默认的 jar 包加载规则下找不到我们的 Application 启动类,也就需要通过 JarLauncher 启动加载。

当然,还有一个原因,Java 规定可执行器的 jar 包禁止嵌套其它 jar 包,在 BOOT-INF/lib 目录下有我们 Spring Boot 应用依赖的所有第三方 jar 包,因此spring-boot-loader 项目自定义实现了 ClassLoader 实现类 LaunchedURLClassLoader,支持加载 BOOT-INF/classes 目录下的 .class 文件,以及 BOOT-INF/lib 目录下的 jar 包。

接下来,我们一起来看看 Spring Boot 的 JarLauncher 这个类

1. JarLauncher

类图:

上面的 WarLauncher 是针对 war 包的启动类,和 JarLauncher 差不多,感兴趣的可以看一看,这里我们直接来看到 JarLauncher 这个类

 

public class JarLauncher extends ExecutableArchiveLauncher { static final String BOOT_INF_CLASSES = "BOOT-INF/classes/"; static final String BOOT_INF_LIB = "BOOT-INF/lib/"; public JarLauncher() { } protected JarLauncher(Archive archive) {

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值