Spring Cloud和Spring Boot深入理解之JAR包项目启动深入理解

本文深入解析SpringBoot项目如何通过JAR包启动,详细介绍了JAR包内部结构,包括BOOT-INF、META-INF和org目录的作用,以及JarLauncher如何加载类和启动应用程序。

Spring Cloud和Spring Boot深入理解之JAR包项目启动深入理解

项目打包出来的JAR包解读

springboot项目一般打出来是个jar包:
在这里插入图片描述
只要用java -jar xxx.jar就可以。
在这里插入图片描述
那他是怎么启动的呢,其实里面封装了好多东西,所以我们就来研究下看看吧,我们先把这个jar包解压看看:
在这里插入图片描述
然后在linux上看了下结构:

BOOT-INF目录:主要是自己写的应用的字节码文件和项目所引用的依赖包。

在这里插入图片描述

META-INF目录:主要是MANIFEST.MF文件。里面有这jar包的入口和启动类

在这里插入图片描述

打开MANIFEST.MF可以看到如下,我们平时好像没怎么接触过JarLauncher,那他到底做了什么呢,后面分析:
在这里插入图片描述

org目录:spring-boot-loader导入的的依赖包的字节码文件

最后是的文件夹其实就是spring-boot-loader导入的的依赖包的字节码形式,只不过是被复制过来的,为什么不是直接放在引用的jar文件夹下呢,因为需要入口类JarLauncher,根据jar的规范,放在引用jar包下的是不会被启动的,所以要单独复制出来:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
总结来说就是三个文件夹:

  1. BOOT-INF:应用程序的类和要引用的jar包
  2. META-INF:入口类和启动类的清单文件
  3. org:spring-boot-loader的导入jar包中的类

jar包是如何启动我们的应用程序的

我们可以用jdwp来对我们运行的jar项目调试,具体jdwp可以百度,其实就是个远程调试啦,我们在5000端口监听客户端连接过来进行调试:
在这里插入图片描述
同时在idea里也要设置:
在这里插入图片描述
然后开始调试,你会发现他就是从JarLauncher开始启动的:
在这里插入图片描述
然后我把一些主要的方法贴一下吧,跟踪调试还是要自己去做,我贴图也不太方便:
执行Launch方法:
在这里插入图片描述

getClassPathArchives获取所有的归档包,也就是jar包:
在这里插入图片描述
然后准备创建自定义的类加载器,这里就是去加载刚才的归档文件,包含我们的应用程序class文件夹和lib下的jar,转换为url:
在这里插入图片描述
然后创建类加载器,是自定义的LaunchedURLClassLoader
在这里插入图片描述
可以看到自定义的加载器就是程序加载的子类:
在这里插入图片描述
至于getMainClass()ExecutableArchiveLauncher类的,其实就是获取了MANIFEST.MFStart-Class: com.wangwei.SpringBootStudyApplication
在这里插入图片描述

然后调用launch方法:
在这里插入图片描述
把要启动的类和类加载器传进去,可以看到他把上下文的类加载器给换了,换成自定义LaunchedURLClassLoader的了,具体里面怎么换的,可以自己去看看:
在这里插入图片描述

然后是创建MainMethodRunner实例,并运行run方法,我把这个类贴出来把,就要见到我们的应用程序启动类了:

/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.loader;

import java.lang.reflect.Method;

/**
 * Utility class that is used by {@link Launcher}s to call a main method. The class
 * containing the main method is loaded using the thread context class loader.
 *
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @since 1.0.0
 */
public class MainMethodRunner {

	private final String mainClassName;

	private final String[] args;

	/**
	 * Create a new {@link MainMethodRunner} instance.
	 * @param mainClass the main class
	 * @param args incoming arguments
	 */
	public MainMethodRunner(String mainClass, String[] args) {
		this.mainClassName = mainClass;
		this.args = (args != null) ? args.clone() : null;
	}

	public void run() throws Exception {
		Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);
		Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
		mainMethod.invoke(null, new Object[] { this.args });
	}

}

继续跟进去看看初始化,已经能看到我们的mainClass的名字:
在这里插入图片描述
最后运行run方法,其实就使用反射来运行我们应用程序中的静态方法,这样才算启动了:
在这里插入图片描述
在这里插入图片描述
最后附上点类图帮助理解继承关系和结构:
在这里插入图片描述
在这里插入图片描述

总结

本篇主要总结了jar包启动项目的流程,里面其实做了很多的事情,springboot自己创建了类加载器来加载,最后还是会启动应用程序,虽然还没涉及到具体springboot内部机制,但是理解这个对整体的把握是有帮助的,希望对你学习springboot有所帮助吧。
在这里插入图片描述

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值