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

本文深入解析了Spring Boot应用如何通过jar包启动,包括MANIFEST.MF中的配置,JarLauncher类的作用,以及自定义ClassLoader如何加载BOOT-INF目录下的类和依赖库。文章详细阐述了从创建JarLauncher实例到启动主类的整个流程,适合对Spring Boot源码感兴趣的读者。
摘要由CSDN通过智能技术生成

该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好!

建议读者私信我领取相关源码注释SpringBoot源码分析结合阅读!

最好对 Spring 源码有一定的了解,如果该篇内容对您有帮助,麻烦点个“赞”,也可以关注小编,感激不尽~

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 指定的就是该工具模块中的一个类

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) {
		super(archive);
	}

	@Override
	protected boolean isNestedArchive(Archive.Entry entry) {
		// 只接受 `BOOT-INF/classes/` 目录
		if (entry.isDirectory()) {
			return entry.getName().equals(BOOT_INF_CLASSES);
		}
		// 只接受 `BOOT-INF/lib/` 目录下的 jar 包
		return entry.getName().startsWith(BOOT_INF_LIB);
	}

	/**
	 * 这里是 java -jar 启动 SpringBoot 打包后的 jar 包的入口
	 * 可查看 jar 包中的 META-INF/MANIFEST.MF 文件(该文件用于对 Java 应用进行配置)
	 * 参考 Oracle 官方对于 jar 的说明(https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html)
	 * 该文件其中会有一个配置项:Main-Class: org.springframework.boot.loader.JarLauncher
	 * 这个配置表示会调用 JarLauncher#main(Str
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值