网站首页 > 技术文章 正文
一、概述
使用过SprongBoot打过jar包的都应该知道,目标文件一般都会生成两个文件,一个是以.jar的包,一个是.jar.original文件。那么使用SpringBoot会打出两个包,而.jar.original的作用是什么呢?还有就是java -jar是如何将一个SpringBoot项目启动的呢?
其实.jar.original是在SpringBoot重新打包之前的原始jar包,内部只包含了项目的用户类,不包含其他的依赖jar包,生成之后,SpringBoot会重新打包之后,最后生成.jar包,内部包含了原始jar包以及其他的引用依赖。
SpringBoot Maven插件打包配置
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.5</version>
<configuration>
//指定SpringBoot项目的main函数的主类入口
<mainClass>xxx.xxx. ..server.bootstrap.LayoutServerApplication</mainClass>
//打成jar包
<layout>JAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
xxx.jar.original文件
只包含用户项目中编写的类及其资源信息,不包含其他依赖jar包
xxx.jar文件
内部包含了原始jar包以及其他的引用依赖jar包
二、SpringBoot xxx.jar包内部结构解析
- BOOT-INF:这个文件夹下有两个文件夹classes用来存放用户类,也就是原始jar.original里的类;还有一个是lib,就是这个原始jar.original引用的依赖。
- META-INF:这里是通过java -jar启动的入口信息,记录了入口类的位置等信息。
- org:org.springframework.boot.loader包下的字节码文件,通过它来启动应用。
这里主要介绍META-INF/MANIFEST.MF文件
Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Archiver-Version: Plexus Archiver
Built-By: admin
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: xxx.layout.server.bootstrap.LayoutServerApplication //项目main函数的主类入口
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.7.5
Created-By: Apache Maven 3.5.2
Build-Jdk: 1.8.0_261
Main-Class: org.springframework.boot.loader.JarLauncher //jar包启动类
三、启动过程解析
从MANIFEST.MF文件中的Main-class指向入口开始。
创建JarLauncher并且通过它的launch()方法开始加载jar包内部信息。
//org.springframework.boot.loader.JarLauncher的main()方法
public static void main(String[] args) throws Exception {
(new JarLauncher()).launch(args);
}
JarLauncher的父类ExecutableArchiveLauncher会去加载jar中的所有文件
public ExecutableArchiveLauncher() {
try {
this.archive = this.createArchive(); //加载归档文件
this.classPathIndex = this.getClassPathIndex(this.archive);
} catch (Exception var2) {
throw new IllegalStateException(var2);
}
}
获取项目中指定的main函数主类
protected void launch(String[] args) throws Exception {
if (!this.isExploded()) {
JarFile.registerUrlProtocolHandler();
}
ClassLoader classLoader = this.createClassLoader(this.getClassPathArchivesIterator());
String jarMode = System.getProperty("jarmode");
//this.getMainClass()获取主类方法
String launchClass = jarMode != null && !jarMode.isEmpty() ? "org.springframework.boot.loader.jarmode.JarModeLauncher" : this.getMainClass();
this.launch(args, launchClass, classLoader);
}
protected String getMainClass() throws Exception {
Manifest manifest = this.archive.getManifest();
String mainClass = null;
if (manifest != null) {
//META-INF/MANIFEST.MF文件中的Start-Class属性值,即项目中自定义的启动主类
mainClass = manifest.getMainAttributes().getValue("Start-Class");
}
if (mainClass == null) {
throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
} else {
return mainClass;
}
}
通过反射调用项目中指定启动主类的main方法
protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
Thread.currentThread().setContextClassLoader(classLoader);
this.createMainMethodRunner(launchClass, args, classLoader).run();
}
public void run() throws Exception {
Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
mainMethod.setAccessible(true);
//反射调用main方法
mainMethod.invoke((Object)null, this.args);
}
//项目中的主类main方法被调用,SpringBoot应用启动
@SpringBootApplication
public class LayoutServerApplication
{
private static final Logger logger = LoggerFactory.getLogger(LayoutServerApplication.class);
public static void main(String[] args)
{
SpringApplication.run(LayoutServerApplication.class, args);
logger.info("-------layout-server启动完成-----");
}
}
猜你喜欢
- 2025-07-28 大模型如何赋能Web渗透测试?(大模型如何赋能web渗透测试工具)
- 2025-07-28 动态切换数据库连接方案(动态切换数据库连接方案是什么)
- 2025-07-28 Apache Tika(apache tika工作流程)
- 2025-07-28 深度探索 Spring Boot3 配置管理:从基础到高级实战
- 2025-07-28 flink sql方式读取kafka实时流数据
- 2025-07-28 小程序源码交付标准详解:必备内容与注意事项
- 2025-07-28 记录程序第一天挖漏洞的过程(漏洞挖掘过程)
- 2025-07-28 springboot从入门到实战开源的全链路追踪系统介绍及实践!
- 2025-07-28 从原理到落地:MCP在Spring AI中的工程实践
- 2025-07-28 刚搭完HBase集群,Phoenix一启动,HBase就全崩了,是什么原因?
- 最近发表
- 标签列表
-
- axure 注册码 (25)
- mutex_lock (30)
- oracleclient (27)
- nfs (25)
- springbatch (28)
- oracle数据库备份 (25)
- dir (26)
- connectionstring属性尚未初始化 (23)
- output (32)
- panel滚动条 (28)
- centos 5 4 (23)
- sql学习 (33)
- c 数组 (33)
- pascal语言教程 (23)
- ppt 教程 (35)
- java7 (24)
- 自适应网站制作 (32)
- server服务自动停止 (25)
- 超链接去掉下划线 (34)
- 什么是堆栈 (22)
- map entry (25)
- ubuntu装qq (25)
- outputstreamwriter (26)
- fill_parent (22)
- mssqlserver jar (30)