spring-boot-maven-plugin插件打包和java -jar命令执行原理

文章目录

  • 1. Maven生命周期
  • 2. jar包结构
    • 2.1 不可执jar包结构
    • 2.2 可执行jar包结构
  • 3. spring-boot-maven-plugin插件打包
  • 4. 执行jar原理

1. Maven生命周期

Maven的生命周期有三种:

  1. clean:清除项目构建数据,较为简单,不深入探讨;
  2. site:建立和部署项目站点,使用的较少,也不深入探讨;
  3. default:定义了项目构建时所需要的所有步骤,是Maven生命周期中最核心最重要的的部分。

本次要深入了解的便是default流程。其生命周期如下:

阶段可否执行说明
validate验证项目是否正确以及所有必要信息是否可用
initializeX初始化构建状态
generate-sourcesX生成编译阶段需要的所有源码文件
process-sourcesX处理源码文件,例如过滤某些值
generate-resourcesX生成项目打包阶段需要的资源文件
process-resourcesX处理资源文件,并复制到输出目录,为打包阶段做准备
compile编译源代码,并移动到输出目录
process-classesX处理编译生成的字节码文件
generate-test-sourcesX生成编译阶段需要的测试源代码
process-test-sourcesX处理测试资源,并复制到测试输出目录
test-compileX编译测试源代码并移动到测试输出目录中
test使用适当的单元测试框架(如junit)运行测试
prepare-packageX在真正打包前执行一些必要的操作
package获取编译后的代码,并按照可发布的格式进行打包,如jar、war或ear文件
pre-integration-testX在集成测试执行之前,执行所需的操作,例如设置环境变量
integration-testX处理和部署所需的包到集成测试能够运行的环境中
post-integration-testX在集成测试被执行后执行必要的操作,例如清理环境
verify对集成测试的结果进行检查,以保证质量达标
install安装打包的项目到本地仓库,以供本地其它项目使用
deploy拷贝最终的包文件到远程仓库中,以共享给其它开发人员和项目

其中可以在Maven常见的Lifecycle中直接执行的有validate、compile、test、package、verify和deploy七种,一般在Maven的plugin标签中,可以通过配置如下配置来指定插件在某个阶段生效,需要注意的是不可随意配置,每个插件可处理的阶段都是不同的。(不配置则执行插件默认的)

<executions><execution><phase>XX</phase><goals><goal>XXXX</goal></goals></execution>
</executions>

今天要深入了解的spring-boot-maven-plugin插件就是在package阶段中生效的。

2. jar包结构

通常而言,jar包分为可执行jar包和不可执行jar包,顾名思义,可执行jar包即可通过命令java -jar直接执行,不可执行jar包通过命令java -jar执行则会报错。

2.1 不可执jar包结构

|-- _jar包根目录|-- 原项目class文件和resource文件|-- _META-INF|-- MANIFEST.MF|-- _maven|-- _项目目录|-- pom.properties|-- pom.xml

上面是经典的不可执行jar包目录,其中MANIFEST.MF文件内容如下:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: xxxxx
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_151

这五项是最基本的,如果使用java -jar执行这些jar包,将会抛出错误码java.launcher.jar.error3,意为没找到Main-Class属性。不同语言展示的最终描述不同,由launcher+对应语言类转换,简体中文在launcher_zh_CN类中转换,{0}为jar包名称,内容如下:

{0}中没有主清单属性

英文在launcher类中转换,{0}为jar包名称,内容如下:

no main manifest attribute, in {0}

2.2 可执行jar包结构

可执行jar包结构挑选经典的springboot启动包来做示范:

|-- _jar包根目录|-- _BOOT-INF|-- _classes|-- 原项目class文件和resource文件|-- _lib|--原项目依赖的jar库文件|-- _META-INF|-- MANIFEST.MF|-- spring-configuration-metadata.json(springboot项目特有)|-- build-info.properties|-- _maven|-- _项目目录|-- pom.properties|-- pom.xml

上一节我们得知了如果在MANIFEST.MF中没有Main-Class属性,使用java -jar命令执行jar包会报错,接下来看看在可执行jar包的结构,MANIFEST.MF中具体有什么属性:

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: XXXX
Implementation-Version: 1.0-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.1.6.RELEASE
Created-By: Maven Archiver 3.4.0
Start-Class: XXX.XXX.XXX.XXXX
Main-Class: org.springframework.boot.loader.JarLauncher

里面有两个很重要的属性:Start-ClassMain-Class,其中Start-Class指的是项目中springboot的SpringApplication启动类,而Main-Class则是jar包的启动类入口。

3. spring-boot-maven-plugin插件打包

springboot插件打包流程

springboot打包插件执行原理:

  1. 读取原jar包:Maven插件都能读MavenProject对象内容,从中可以读取到Artifact信息,调用该对象的getFile()方法即可获取原jar包文件对象;
  2. 读取项目依赖jar库:直接使用MavenProject对象的getArtifacts()方法即可获取依赖的jar库;
  3. 加载launchScript:读取embeddedLaunchScript配置,并构建LaunchScript对象;
  4. 重新改写MANIFEST.MF:到此步骤开始为repackage的核心流程,改写清单文件时最主要的便是写入Start-ClassMain-Class属性,除此之外还会写入jar库和原项目文件目录属性;
  5. 写入spring-boot-loader包文件:该包是springboot对接java -jar执行命令的核心处理逻辑,springboot打包后加入的Main-Class: org.springframework.boot.loader.JarLauncher属性指向的类便是此包中的jar包启动类,如果war包则会写入war包启动类;
  6. 写入原项目文件:原项目文件会被挪到BOOT-INF/classes/目录下;
  7. 写入项目依赖jar库:原项目依赖的jar库会被写入到BOOT-INF/lib/目录下。

如果要看spring-boot-maven-plugin插件打包源码以分析原理,可导入插件的依赖,此时就能看到该插件的源码。如果使用的是IDEA,下载源码后打上断点,在执行package时,使用debug模式启动也能直接进行调试。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>XXXXX</version>
</dependency>

4. 执行jar原理

将会分析执行java -jar命令后,Java程序调用到Springboot启动类main方法的流程。

执行jar包到springboot入口流程

  1. JVM启动,执行加载主函数LoadMainClass:此时是在JVM底层实现的,里面指定了LauncherHelper类;
  2. 执行LauncherHelpercheckAndLoadMain方法:JVM将会调用LauncherHelpercheckAndLoadMain方法,解析并校验jar包,并获取主要的启动类;
  3. 解析jar的MANIFEST.MF文件:在此方法中会完成读取MANIFEST.MF文件,主要是读取其中的Main-Class属性,并做jar包启动的校验;
  4. GetStaticMethodID方法:JVM获取到Main-Class类对象,调用Main-Class类对象的main方法;
  5. 执行JarLauncher的main方法:JarLauncher继承自Launcher,main方法最后还是会调用到Launcher.launch()方法中;
  6. 读取jar的Start-Class:此时会读取jar包的Start-Class属性,该属性就是原项目的SpringApplication启动类;
  7. 调用启动类的main方法:调用MainMethodRunner的run方法,里面会调用Start-Class类的main方法
  8. 此时调入到自定义的启动类中,完成启动Springboot程序的入口程序。

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

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

相关文章

spring容器创建bean过程中使用到的几个factory

文章目录 前述BeanFactoryFactoryBeanObjectFactory 前述 spring我们可以理解为一个帮我们管理bean的容器&#xff0c;使用spring框架之前创建bean都是通过new的方式&#xff0c;使用spring框架之后&#xff0c; 我们只需要告诉spring框架我们有那些bean&#xff0c;它会帮我们…

k8s证书过期处理

证书一共分为 根CA&#xff08;ca.crt&#xff09; master各组件的证书&#xff08;包括etcd、apiserver、front-proxy、controller-manager等各种&#xff09; kubelet证书 k8s证书有效期说明&#xff1a; 1、原生版本有效期master节点&#xff1a; /etc/kubernetes/ssl/…

YOLOv10改进系列,YOLOv10损失函数更换为Powerful-IoU(2024年最新IOU),助力高效涨点

改进前训练结果: 改进后的结果: 摘要 边界框回归(BBR)是目标检测中的核心任务之一,BBR损失函数显著影响其性能。然而,观察到现有基于IoU的损失函数存在不合理的惩罚因子,导致回归过程中锚框扩展,并显著减缓收敛速度。为了解决这个问题,深入分析了锚框扩展的原因。针…

基于 K8S kubernetes 的常见日志收集方案

目录 1、日志对我们来说到底重不重要&#xff1f; 2、常见的日志收集方案 2.1 EFK 2.2 ELK Stack 2.3 ELKfilebeat 2.4 其他方案 2、elasticsearch组件介绍 3、filebeat组件介绍 3.1 filebeat和beat关系 3.2 filebeat是什么&#xff1f; 3.3 Filebeat工作原理 3.4 …

ELFK日志分析平台,架构和通信

整个架构&#xff0c;加上跳板机&#xff0c;总共12台机器 技术方案&#xff1a; 1. 配置nfs服务器&#xff0c;为web集群提供共享网络文件系统 # 部署 NFS 服务 [rootnfs ~]# dnf install -y nfs-utils [rootnfs ~]# vim /etc/exports /var/webroot 192.168.1.0/24(rw,…

xml重点笔记(尚学堂 3h)

XML:可扩展标记语言 主要内容(了解即可) 1.XML介绍 2.DTD 3.XSD 4.DOM解析 6.SAX解析 学习目标 一. XML介绍 1.简介 XML(Extensible Markup Language) 可扩展标记语言&#xff0c;严格区分大小写 2.XML和HTML XML是用来传输和存储数据的。 XML多用在框架的配置文件…

剖析 MySQL 数据库连接池(C++版)

目录 ☀️0. 前言 &#x1f324;️1. 数据库连接池概述 ⛅1.1 服务器与数据库交互 ⛅1.2 MySQL 数据库网络模型 ⛅1.3 MySQL 连接驱动安装 ⛅1.4 同步&#xff08;synchronous&#xff09;连接池与异步&#xff08;asynchronous&#xff09;连接池 ⛅1.5 同步连接池和异…

记录开发一个英语听力训练网站

背景 在当前全球经济衰退的背景下&#xff0c;IT相关的工作在国内的竞争也是越来越激烈&#xff0c;为了能够获得更多的可能性&#xff0c;英语的学习也许能为程序员打开一扇新的窗户&#xff0c;比如很多远程的工作尤其是国际化背景的工作团队&#xff0c;英语的协作沟通是必…

yolov8-obb中存在的一个bug

yolov8支持OBB目标检测,且能提供较好的性能。 但是最近在使用yolov8-obb的过程中,发现yolov8-obb存在一个bug。即训练数据如果包含不带旋转角度的水平目标时,训练出的模型,经常会输出垂直的检测框,需要旋转90度以后才能得到最终结果。把yolov8-obb相关的源码阅读一遍才发…

初始爬虫5

响应码&#xff1a; 数据处理&#xff1a; re模块&#xff08;正则表达式&#xff09; re模块是Python中用于正则表达式操作的标准库。它提供了一些功能强大的方法来执行模式匹配和文本处理。以下是re模块的一些常见用法及其详细说明&#xff1a; 1. 基本用法 1.1 匹配模式 …

STM32 的 RTC(实时时钟)详解

目录 一、引言 二、RTC 概述 三、RTC 的工作原理 1.时钟源 2.计数器 3.闹钟功能 4.备份寄存器 四、RTC 寄存器 1.RTC_TR&#xff08;Time Register&#xff0c;时间寄存器&#xff09; 2.RTC_DR&#xff08;Date Register&#xff0c;日期寄存器&#xff09; 3.RTC_S…

TCP 拥塞控制:一场网络数据的交通故事

从前有条“高速公路”&#xff0c;我们叫它互联网&#xff0c;而这条公路上的车辆&#xff0c;则是数据包。你可以把 TCP&#xff08;传输控制协议&#xff09;想象成一位交通警察&#xff0c;负责管理这些车辆的行驶速度&#xff0c;以防止交通堵塞——也就是网络拥塞。 第一…

【MPC】无人机模型预测控制复现Data-Driven MPC for Quadrotors项目(Part 1)

无人机模型预测控制复现Data-Driven MPC for Quadrotors项目 参考链接背景和问题方法与贡献实验结果安装ROS创建工作空间下载RotorS仿真器源码和依赖创建Python虚拟环境下载data_driven_mpc仓库代码下载并配置ACADO求解器下载并配置ACADO求解器的Python接口下载并配置rpg_quadr…

基于密码的大模型安全治理的思考

文章目录 前言一、大模型发展现状1.1 大模型技术的发展历程1.2 大模型技术的产业发展二、大模型安全政策与标准现状2.1 国外大模型安全政策与标准2.2 我国大模型安全政策与标准前言 随着大模型技术的迅速发展和广泛应用,其安全性问题日益凸显。密码学作为网络空间安全的核心技…

如何简化机器人模型,加速仿真计算与可视化

通常,我们希望将自己设计的机器人模型导入仿真环境。由于是通过 CAD 软件设计的,导出的 urdf 使用 STL 或 DAE 文件来表示 3D 几何。但原始的 STL 或 DAE 文件通常过于复杂(由数十万个三角面片组成),这会减慢仿真速度,有时也会导致仿真软件报错(如Webots)。为了在正确描述…

【Linux】调试和Git及进度条实现

这里是阿川的博客&#xff0c;祝您变得更强 ✨ 个人主页&#xff1a;在线OJ的阿川 &#x1f496;文章专栏&#xff1a;Linux入门到进阶 &#x1f30f;代码仓库&#xff1a; 写在开头 现在您看到的是我的结论或想法&#xff0c;但在这背后凝结了大量的思考、经验和讨论 目录 1.…

KVM创建的虚拟机无法访问外网

基础环境如下&#xff1a; [rootlocalhost ~]# virsh domifaddr CentOS7_YFName MAC address Protocol Address -------------------------------------------------------------------------------vnet0 52:54:00:cb:a6:0d ipv4 192.168.…

Java中的事务管理

1.1 事务管理 1.1 事务回顾 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位。事务会把所有的操作作为一个整体&#xff0c;一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功&#xff0c;要么同时失败。 怎么样来控制这组操作&#xff0c;让这组操…

OpenCV高阶操作

在图像处理与计算机视觉领域&#xff0c;OpenCV&#xff08;Open Source Computer Vision Library&#xff09;无疑是最为强大且广泛使用的工具之一。从基础的图像读取、 1.图片的上下&#xff0c;采样 下采样&#xff08;Downsampling&#xff09; 下采样通常用于减小图像的…

RabbitMQ(高阶使用)延时任务

文章内容是学习过程中的知识总结&#xff0c;如有纰漏&#xff0c;欢迎指正 文章目录 1. 什么是延时任务&#xff1f; 1.1 和定时任务区别 2. 延时队列使用场景 3. 常见方案 3.1 数据库轮询 优点 缺点 3.2 JDK的延迟队列 优点 缺点 3.3 netty时间轮算法 优点 缺点 3.4 使用消息…