SpringBoot: 启动流程和类装载

前面我们学过Spring定制了自己的可执行jar,将真正执行时需要的类和依赖放到BOOT-INF/classes、BOOT-INF/lib来,为了能够识别这些为止的源文件,Spring定制了自己类加载器,本节我们来讲解这个类加载器。本节涉及的内容主要包括:

  1. SpringBoot启动流程
  2. SpringBoot类加载器

1. SpringBoot启动流程

在SpringBoot的可执行jar中,配置了MANIFEST.MF的Main-Class设置为JarLauncher,JarLauncher的加载过程如下图

  1. 调用Launcher.launch方法,开始引导程序
  2. 通过Handlers.reigster()注册URLStreamHandler的jar协议处理类,支持getResource读取BOOT-INF/下的内容
  3. 通过archive.getClassPathUrls()筛选可执行jar的所有元素,通过JarLauncher.isIncludedOnClassPath过滤,筛选出所有ClassPath元素
  4. 用这些筛选的ClassPath创建LaunchedClassLoader
  5. 使用LaunchedClassLoader加载MANIFEST.MF的Start-Class
  6. 反射调用main方法

2. SpringBoot类加载器

使用URLClassLoader加载SpringBoot Jar时不会加载BOOT-INF下的classes、lib的类和依赖包,SpringBoot通过自定义类加载器LaunchedClassLoader解决这个问题。它继承自URLClassLoader。参照SpringBoot的启动流程,我们讲手动使用LaunchedClassLoader加载可执行jar,并尝试引导SpringBoot应用。

1. 创建Archive

从启动流程可以看到,核心流程是先通过Archive.getClassPathUrls()获取所有的ClassPath,包括jar文件中内嵌的。JarFileArchive是包可见的,用Archive.create创建实例

URLClassLoader ucl = new URLClassLoader("MyURLClassLoader", new URL[]{url}, null);
Class<?> clazz = ucl.loadClass("org.springframework.boot.loader.JarLauncher");
Archive archive = Archive.create(clazz);
2. 枚举内嵌Jar

Archive提供了getClassPathUrls筛选所有的Archive.Entry,Archive和Archive.Entry可以按JarFile、JarEntry来理解,正是它们有不同的抽象,不仅仅支持jar文件。

Set<URL> su = archive.getClassPathUrls((Archive.Entry e) -> true);
su.stream().forEach(x -> System.out.println(x));

这个方法的输出是这样的,它会是一些jar:nested:协议的URL集合。我们知道URLClassLoader接收一组根路径实现类加载,把这个集合都传递给URLClassLoader是不是就可以了呢?

3. 使用内嵌Jar

讲上一步获取的Set作为根路劲提供给URLClassLoader

URLClassLoader lcl = new URLClassLoader("MyNested", su.toArray(URL[]::new),null);
clazz = lcl.loadClass("com.keyniu.yangsi.YangsiApplication");
System.out.println(clazz);

并不能正常工作,因为jar:nested不是Java支持的内嵌协议

4. 注册协议处理器

在SpringBoot的启动流程里我们专门有提到过Handlers,它就是用来注册协议处理器的在使用3.3.3的代码之前,执行如下代码,就能执行成功了。

Handlers.register();

Handlers.register()实际是通过包名: org.springframework.boot.loader.net.protocol,注册了jar、nested(包名)这两个协议的处理器Handler(对于包下固定类名)

5. 启动SpringBoot

现在我们已经能完整的加载整个SpringBoot可以执行jar了,我们是不是能像JarLauncher一样调用Start-Class的main方法来启动应用呢?答案是肯定的。

private static void testLaunched(URL url) throws Exception {URLClassLoader ucl = new URLClassLoader("MyURLClassLoader", new URL[]{url}, null);Class<?> clazz = ucl.loadClass("org.springframework.boot.loader.JarLauncher");Archive archive = Archive.create(clazz);Set<URL> su = archive.getClassPathUrls((Archive.Entry e) -> true);Handlers.register();su.add(url);LaunchedClassLoader lcl = new LaunchedClassLoader(false, su.toArray(URL[]::new), null);clazz = Class.forName("com.keyniu.yangsi.YangsiApplication", false, lcl);               // 启动类Method mainMethod = clazz.getDeclaredMethod("main", String[].class);// main方法mainMethod.setAccessible(true);mainMethod.invoke(null, (Object) new String[0]);                                        // 调用main方法
}

5. 参考资料

  1. JVM Specification: Loading、Linking And Initializing,Chapter 5. Loading, Linking, and Initializing
  2. SClass Loaders in Java | Baeldung

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/25481.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux部署调度工具xxl-job

背景&#xff1a; Pentaho Data Integration&#xff08;kettle&#xff09;作为用户规模最多的开源ETL工具&#xff0c;强大简洁的功能深受广大ETL从业者的欢迎。但kettle本身的调度监控功能却非常弱。Pentaho官方都建议采用crontab(Unix&#xff0c;linux平台)和计划任务(Win…

UFS(Universal Flash Storage)详解

标签: UFS; Universal Flash Storage; UFS(Universal Flash Storage)详解 背景 Universal Flash Storage(UFS)是一种基于闪存存储技术的高性能存储解决方案,由JEDEC(Solid State Technology Association)制定和标准化。UFS旨在为移动设备、数码相机、虚拟现实设备…

kaggle竞赛实战8——其他方案之XGBOOST及NLP特征优化

之前都用的集成算法&#xff0c;发现差异不大&#xff0c;考虑在特征优化上提升数据质量&#xff0c;用NLP算法优化id列 有两种方法&#xff0c;分别是countervector和TF-IDF&#xff0c;前者就是词频&#xff0c;后者由TF&#xff08;词频&#xff09;和IDF&#xff08;反文档…

群体优化算法----树蛙优化算法介绍以及应用于资源分配示例

介绍 树蛙优化算法&#xff08;Tree Frog Optimization Algorithm, TFO&#xff09;是一种基于群体智能的优化算法&#xff0c;模拟了树蛙在自然环境中的跳跃和觅食行为。该算法通过模拟树蛙在树枝间的跳跃来寻找最优解&#xff0c;属于近年来发展起来的自然启发式算法的一种 …

抽象的java入门1.3.2

前言&#xff1a; 全新版本的函数&#xff08;方法&#xff09;定义&#xff0c;更简单 1.优化了验证过程&#xff0c;直击本质 2.新增目前一图流 正片&#xff1a; 函数的结构可以分为三部分&#xff1a;函数名&#xff0c;参数&#xff0c;函数体 一生二&#xff0c;二生…

6.9总结

Vue生命周期 生命周期&#xff1a;指一个对象从创建到销毁的整个过程生命周期的八个阶段&#xff1a;每触发一个生命周期事件&#xff0c;会自动执行一个生命周期的方法&#xff08;钩子&#xff09; mounted&#xff1a;挂载完成&#xff0c;Vue初始化成功&#xff0c;HTML渲…

Linux 35.5 + JetPack v5.1.3@Fast-Planner编译安装

Linux 35.5 JetPack v5.1.3Fast-Planner安装 1. 源由2. 编译&安装Step 1&#xff1a;依赖库安装Step 2&#xff1a;建立工程Step 3&#xff1a;编译工程Step 4&#xff1a;安装工程 3. 问题汇总3.1 Eigen3 组件问题3.2 pcl_conversions 组件问题3.3 cv_bridge组件问题3.4 …

ssm629基于SSM的二手交易平台设计与开发+jsp【已测试】

前言&#xff1a;&#x1f469;‍&#x1f4bb; 计算机行业的同仁们&#xff0c;大家好&#xff01;作为专注于Java领域多年的开发者&#xff0c;我非常理解实践案例的重要性。以下是一些我认为有助于提升你们技能的资源&#xff1a; &#x1f469;‍&#x1f4bb; SpringBoot…

智慧社区整体解决方案

1.智慧社区整体建设方案内容 2.整体功能介绍

linux动态调试 dev_dbg

动态调试使用方法 打开内核动态调试开关&#xff0c;make menuconfig选中CONFIG_DYNAMIC_DEBUG以及CONFIG_DEBUG_FS Linux启动后&#xff0c;使用命令行挂载上dbgfs 1. mkdir /mnt/dbg 2. mount -t debugfs none /mnt/dbg 1.控制某个文件所有dev_dbg()&#xff0c; echo -n &q…

sqli-labs 靶场 less-11~14 第十一关、第十二关、第十三关、第十四关详解:联合注入、错误注入

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它&#xff0c;我们可以学习如何识别和利用不同类型的SQL注入漏洞&#xff0c;并了解如何修复和防范这些漏洞。Less 11 SQLI DUMB SERIES-11判断注入点 尝试在用户名这个字段实施注入,且试出SQL语句闭合方式为单…

电子阅览室有何作用

随着互联网的快速发展&#xff0c;电子阅览室逐渐成为人们获取知识的新方式。它为读者提供了便捷、高效的阅读体验&#xff0c;具有诸多作用。首先&#xff0c;电子阅览室拥有丰富的电子书籍资源&#xff0c;涵盖了各个领域的知识。无论是文学作品还是学术论文&#xff0c;读者…

解决Win10系统ping不通、无法远程的问题

1、概述 某天要使用微软的远程桌面程序mstsc.exe远程到旁边的一台测试电脑上,结果远程不了,ping都ping不通,于是详细研究了这个问题。在此大概地记录一下该问题排查的过程,以供参考。 2、ping不通 使用mstsc.exe远程到测试电脑,远程不了,没有反应。于是手动ping一…

英语学习笔记33——A fine day

A fine day 风和日丽 词汇 Vocabulary day n. 日子&#xff0c;白天 复数&#xff1a;days 常见节日&#xff1a;Mothers’ Day 母亲节      Fathers’ Day 父亲节      Teachers’ Day 教师节      Children’s Day 儿童节      Women’s Day 妇女节 c…

html--宇航员404

<!doctype html> <html> <head> <meta charset"utf-8"> <title>太空404</title><style> html {margin: 0;padding: 0;background-color: white; }body, html {width: 100%;height: 100%;overflow: hidden; }#svgContainer…

【数据库】SQL--DDL(初阶)

文章目录 DDL1. 数据库操作1.1. 表操作1.1.1 创建1.1.2. 查询 2. 数据类型及案例2.1 数值类型2.2 字符串类型2.3 日期时间类型2.4 案例练习 3. 表操作--修改3.1 添加字段3.2 修改字段3.3 修改表名 4. 表操作-删除4.1 删除字段4.2 删除表 5. DDL小结 更多数据库MySQL系统内容就在…

Pytorch 实现目标检测二(Pytorch 24)

一 实例操作目标检测 下面通过一个具体的例子来说明锚框标签。我们已经为加载图像中的狗和猫定义了真实边界框&#xff0c;其中第一个 元素是类别&#xff08;0代表狗&#xff0c;1代表猫&#xff09;&#xff0c;其余四个元素是左上角和右下角的(x, y)轴坐标&#xff08;范围…

Java数据结构与算法(盛水的容器)

前言 针对此类算法题&#xff0c;最基本是暴力算法求解&#xff0c;暴力算法基本是固定的套路。在暴力算法基础上寻求优化思路&#xff0c;是否可以单词遍历能否得到所要的结果。此时需要观察数据的特征&#xff0c;推演数据变化对结果的影响&#xff0c;从而找到合理的解题思…

Web前端Text:深入解析与实践应用

Web前端Text&#xff1a;深入解析与实践应用 在Web前端开发中&#xff0c;Text作为页面内容的重要组成部分&#xff0c;其处理和展示方式直接关系到用户体验和页面效果。本文将围绕Web前端Text的四个方面、五个方面、六个方面和七个方面进行详细解析&#xff0c;带您领略其奥秘…

【网络安全】【深度学习】【入侵检测】SDN模拟网络入侵攻击并检测,实时检测,深度学习

文章目录 1. 前言2. Mininet 和 Ryu 的区别2.1 Mininet2.2 Ryu2.3 总结 3. 模拟攻击3.1 环境准备3.2 创建 Mininet 网络拓扑3.2 启动 Ryu 控制器3.3 模拟网络攻击3.4 捕获流量 4. 实时异常检测4.1 在 Ryu 控制器中4.2 在 h2 机器上的实验结果4.3 深度学习模型部署上h2机器 帮助…