Spring Boot 打包成Jar包运行原理分析

 更新时间:2023年09月18日 10:37:47   作者:Mr_姚  
这篇文章主要为大家介绍了Spring Boot 打包成Jar包运行的原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

SpringBoot打包

相比与传统的Java打包方式,使用SpringBoot打包插件打包成jar包后,可以直接使用java -jar 运行SpringBoot项目,本篇就来分析一下运行的原理。

SpringBoot打包插件

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

打包完后会生成两个文件,一个***.jar***.jar.original

.jar文件是SpringBoot打包后生成的文件,.jar.original是用原生方式打包生成的文件,对比一下两个的区别

.jar.original文件

.jar文件

.jar.original就是普通的jar打包的结构,这里主要看.jar文件的结构:

  • META-INFO目录:META-INFO/MANIFEST.MF里包含了jar包的元数据,包含了项目的启动类等信息.

  • org目录:该目录下包含的是启动项目的一些类,启动的过程就在这个包里。

  • BOOT-INFO目录:本地项目的代码(BOOT-INF/classes),以及所需的以依赖(BOOT-INFO/lib)

重点 META-INFO/MANIFEST.MF

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.4.5
Created-By: Maven Jar Plugin 3.2.0
Main-Class: org.springframework.boot.loader.JarLauncher

这里有几个重点的字段

  • Main-Class :jar包启动类,这是java规定的字段,存在这个字段的情况下, 在java -jar时,jar包才会运行起来
  • Start-Class:本地项目的启动类
  • Spring-Boot-Classes:加载应用类的入口
  • Spring-Boot-Lib:项目所需的依赖

有了Main-Class启动类,那就直接进入到JarLauncher里查看运行的过程

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

JarLaunchermain方法里调用了launch方法,launch方法的具体实现在JarLauncher的抽象父类Launcher中实现

    protected void launch(String[] args) throws Exception {
        if (!this.isExploded()) {
            JarFile.registerUrlProtocolHandler();
        }
        ClassLoader classLoader = this.createClassLoader(this.getClassPathArchivesIterator());
        String jarMode = System.getProperty("jarmode");
        String launchClass = jarMode != null && !jarMode.isEmpty() ? "org.springframework.boot.loader.jarmode.JarModeLauncher" : this.getMainClass();
        this.launch(args, launchClass, classLoader);
    }

首先获取了类加载器。

然后获取jarMode,再根据jarMode获取launchClass,如果没有设置jarMode,则根据getMainClass方法获取,getMainClass的具体实现在ExecutableArchiveLauncher中实现

 protected String getMainClass() throws Exception {
        Manifest manifest = this.archive.getManifest();
        String mainClass = null;
        if (manifest != null) {
            mainClass = manifest.getMainAttributes().getValue("Start-Class");
        }
        if (mainClass == null) {
            throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
        } else {
            return mainClass;
        }
    }

getMainClass里获取了MANIFEST.MF文件里Start-Class字段的值,也就是本地项目的启动类。

最后调用this.launch(args, launchClass, classLoader);

    protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
        Thread.currentThread().setContextClassLoader(classLoader);
        this.createMainMethodRunner(launchClass, args, classLoader).run();
    }

调用MainMethodRunnerrun()方法

    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);
        mainMethod.invoke((Object)null, this.args);
    }

run()方法里通过反射拿到了项目的启动类的main方法,从而启动本地项目。

以上就是Spring Boot 打包成Jar包运行的原理的详细内容,更多关于Spring Boot Jar包的资料请关注脚本之家其它相关文章!

相关文章

  • Java实现浏览器大文件上传的示例详解

    Java实现浏览器大文件上传的示例详解

    文件上传是许多项目都有的功能,用户上传小文件速度一般都很快,但如果是大文件几个g,几十个g的时候,上传了半天,马上就要完成的时候,网络波动一下,文件又要重新上传,所以本文给大家介绍了Java实现浏览器大文件上传的示例,需要的朋友可以参考下
    2024-07-07
  • jar包和war包区别解析

    jar包和war包区别解析

    jar是java普通项目打包,通常是开发时要引用通用类,打成jar包便于存放管理,war是java web项目打包,web网站完成后,打成war包部署到服务器,目的是为了节省资源,提供效率,这篇文章主要介绍了jar包和war包区别及理解,需要的朋友可以参考下
    2023-07-07
  • Maven脚手架如何基于jeecg实现快速开发

    Maven脚手架如何基于jeecg实现快速开发

    这篇文章主要介绍了Maven脚手架如何基于jeecg实现快速开发,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • SpringBoot如何优雅的输出异常信息

    SpringBoot如何优雅的输出异常信息

    在Java中,异常(Exception)是Java程序在运行过程中出现的一种特殊情况,会中断正常的程序流程,异常可以是运行时错误,也可以是编程错误,本文将给大家详细的介绍一下SpringBoot如何优雅的输出异常信息,需要的朋友可以参考下
    2023-09-09
  • SpringBoot集成itextpdf实现根据模板动态生成PDF

    SpringBoot集成itextpdf实现根据模板动态生成PDF

    这篇文章主要为大家详细介绍了SpringBoot如何集成itextpdf实现根据模板动态生成PDF,文中的示例代码讲解详细,需要的小伙伴可以参考一下
    2024-03-03
  • mybatis调用mysql存储过程并获取返回值方式

    mybatis调用mysql存储过程并获取返回值方式

    这篇文章主要介绍了mybatis调用mysql存储过程并获取返回值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • java编程小白进阶包的作用详解

    java编程小白进阶包的作用详解

    这篇文章主要为大家介绍了java编程中包的作用详解,文中通过示例分析方便大家更容易理解包的作用,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-10-10
  • java后端实现信息分页查询的示例代码

    java后端实现信息分页查询的示例代码

    在一个页面展示大量的用户信息不便于观看,因此就需要采用分页展示的方法,本文就来为大家介绍一下java后端如何实现信息分页查询,需要的小伙伴可以参考下
    2023-11-11
  • IDEA中java断言assert语法及使用

    IDEA中java断言assert语法及使用

    这篇文章主要介绍了IDEA中java断言assert语法详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • spring aop Pointcut execution规则介绍

    spring aop Pointcut execution规则介绍

    这篇文章主要介绍了spring aop Pointcut execution规则,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11

最新评论