SpringBoot的jar包如何启动

本文详细介绍了SpringBoot的jar包如何启动,包括jar包的内部结构、加载过程。重点解析了Archive、Launcher、Spring.Loader.JarFile和JarEntry等关键类的作用,以及从MANIFEST.MF指定的入口开始,如何加载并执行应用程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot的jar包如何启动

一、简介

​ 使用过SprongBoot打过jar包的都应该知道,目标文件一般都会生成两个文件,一个是以.jar的包,一个是.jar.original文件。那么使用SpringBoot会打出两个包,而.jar.original的作用是什么呢?还有就是java -jar是如何将一个SpringBoot项目启动,之间都进行了那些的操作?

​ 其实.jar.originalmavenSpringBoot重新打包之前的原始jar包,内部只包含了项目的用户类,不包含其他的依赖jar包,生成之后,SpringBoot重新打包之后,最后生成.jar包,内部包含了原始jar包以及其他的引用依赖。以下提及的jar包都是SpringBoot二次加工打的包。

二、jar包的内部结构

SpringBoot打出的jar包,可以直接通过解压的方式查看内部的构造。一般情况下有三个目录。

  • BOOT-INF:这个文件夹下有两个文件夹classes用来存放用户类,也就是原始jar.original里的类;还有一个是lib,就是这个原始jar.original引用的依赖。
  • META-INF:这里是通过java -jar启动的入口信息,记录了入口类的位置等信息。
  • org:Springboot loader的代码,通过它来启动。

这里主要介绍一下/BOOT-INF/MANIFEST.MF文件

Manifest-Version: 1.0
Implementation-Title: springboot-server
Implementation-Version: 0.0.1-SNAPSHOT
Archiver-Version: Plexus Archiver
Built-By: Administrator
Implementation-Vendor-Id: cn.com.springboot
Spring-Boot-Version: 1.5.13.RELEASE
Implementation-Vendor: Pivotal Software, Inc.
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: cn.com.springboot.center.AuthEenterBootstrap
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.6.1
Build-Jdk: 1.8.0_241
Implementation-URL: http://projects.spring.io/spring-boot/auth-server/

Main-Class:记录了java -jar的启动入口,当使用该命令启动时就会调用这个入口类的main方法,显然可以看出,Springboot转移了启动的入口,不是用户编写的xxx.xxx.BootStrap的那个入口类。

Start-Class:记录了用户编写的xxx.xxx.BootStrap的那个入口类,当内嵌的jar包加载完成之后,会使用LaunchedURLClassLoader线程加载类来加载这个用户编写的入口类。

三、加载过程
1.使用到的一些类

3.1.1 Archive

​ 归档文件接口,实现迭代器接口,它有两个子类,一个是JarFileArchivejar包文件使用,提供了返回这个jar文件对应的url、或者这个jar文件的MANIFEST文件数据信息等操作。是ExplodedArchive是文件目录的使用也有获取这个目录url的方法,以及获取这个目录下的所有Archive文件方法。

3.1.2 Launcher

​ 启动程序的基类,这边最后是通过JarLauncher#main()来启动。ExecutableArchiveLauncher是抽象类,提供了获取Start-Class类路径的方法,以及是否还有内嵌对应文件的判断方法和获取到内嵌对应文件集合的后置处理方法的抽象,由子类JarLauncherWarLauncher自行实现。

3.1.3 Spring.loader下的JarFile和JarEntry

jarFile继承于jar.util.jar.JarFileJarEntry继承于java.util.jar.JarEntry,对原始的一些方法进行重写覆盖。每一个JarFileArchive都拥有一个JarFile方法,用于存储这个jar包对应的文件,而每一个JarFile都有一个JarFileEntries,JarFileEntries是一个迭代器。总的来说,在解析jar包时,会将jar包内的文件封装成JarEntry对象后由JarFile对象保存文件列表的迭代器。所以JarFileArchiveJarFileEntries之间是通过JarFile连接,二者都可以获取到JarFile对象。

2.过程分析

MANIFEST.MF文件中的Main-class指向入口开始。

创建JarLauncher并且通过它的launch()方法开始加载jar包内部信息。

public static void main(String[] args) throws Exception {
   
  new JarLauncher().launch(args);
}

JarLauncher的空构造方法时一个空实现,刚开始看的时候还懵了一下,以为是在后续的操作中去加载的文件,其实不然,在创建时由父类ExecutableArchiveLauncher的构造方法去加载的文件。

	public ExecutableArchiveLauncher() {
   
		try {
   
		   // 加载为归档文件对象
		   this.archive = createArchive();
		 }
		 catch (Exception ex) {
   
		   throw new IllegalStateException(ex);
		 }
	}


	/**
	 * 具体的加载方法
	 */
	protected final Archive createArchive() throws Exception {
   
		 ProtectionDomain protectionDomain = getClass().getProtectionDomain();
		 CodeSource codeSource = protectionDomain.getCodeSource();
		 URI location = (codeSource == null ? null : codeSource.getLocation().toURI());
		 String path = (location == null ? null : location.getSchemeSpecificPart());
		 if (path == null) {
   
		   throw new IllegalStateException("Unable to determine code source archive");
		 }
		 File root = new File(path);
		 if (!root.exists()) {
   
		   throw new IllegalStateException(
		     "Unable to determine code source archive from " + root);
		 }
		 // 判断路径是否是一个文件夹,是则返回ExplodedArchive对象,否则返回JarFileArchive
		 return (root.isDirectory() ? 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值