面试官居然我问SpringBoot 是如何通过jar包启动的?- 第373篇

图片

关历史文章(阅读本文前,您可能需要先看下之前的系列👇

国内最全的Spring Boot系列之四

享元模式:共享女友 - 第355篇

从Spring和Spring MVC来更加理解Spring Boot的存在 - 第368篇

面试官居然我问SpringBoot 是如何通过jar包启动的?- 第373篇

对于SpringBoot打包的jar文件,我们呢,只通过java -jar一行命令便可以启动一个web项目,这如此神奇的效果是SpringBoot是如何帮你完成的呢?

一、从spring-boot-maven-plugin说起

       对于SpringBoot项目,我们会在pom.xml文件添加打包插件spring-boot-maven-plugin,那么执行打包的时候,会生成相应的jar文件,比如:

spring-boot-hello-0.0.1-SNAPSHOT.jar

       我们打开这个jar看下都有什么呢?

       通过这里我们可以看出spring-boot-maven-plugin做了几个重要的事情:

(1)生成核心的文件MANIFEST.MF;

(2)把依赖的jar包进行打包;

       这里普及一个知识点:jar里打包进去了别的jar包,这样的jar称为fat jar(胖的jar)。

       标准的解释:在java中,通常将应用程序及其依赖jar一起打包到一个独立的jar中,就叫fat jar,它也叫uberJar。

       在上面最重要的信息就是:MANIFEST.MF,我们进去一探究竟。

二、进入MANIFEST.MF一探究竟

       我们脱去MANIFEST.MF的外衣看看里面是什么鬼?

       我们把jar解压,然后使用记事本打开MANIFEST.MF文件:

       在MANIFEST.MF文件中,重要的是两个属性是:

Start-Class: com.kfit.springboothellosts.SpringBootHelloStsApplication

Main-Class: org.springframework.boot.loader.JarLauncher

       我们会发现Start-Class指向的是我们的启动类,也就是注解了@SpringBootApplication的类。

       Main-Class又是什么呢?接着往下看,为您揭晓。

三、java -jar做了什么?

       先要弄清楚java -jar命令做了什么,在oracle官网找到了该命令的描述:

        If the -jar option is specified, its argument is the name of the JAR file containing class and resource files for the application. The startup class must be indicated by the Main-Class manifest header in its source code.

       翻译过来的大体意思就是:使用-jar参数时,后面的参数是jar的文件名称(本例子中是spring-boot-hello-0.0.1-SNAPSHOT.jar),该jar文件中包含的是class和资源文件;在mainfest文件中有Main-Class的定义;Main-Class的源码中指定了整个应用的启动类。

       简单来说就是:java -jar会去找jar中的manifest文件,找到属性属性Main-Class,从而找到真正的启动类。

四、JarLauncher是什么东东呢?

       对于Spring Boot项目的Main-Class中的值是org.springframework.boot.loader.JarLauncher,那么当我们执行命令:

Java -jar  spring-boot-hello-0.0.1-SNAPSHOT.jar

的时候,那么会找到.jar文件中的

Main-Class属性值org.springframework.boot.loader.JarLauncher,然后执行JarLauncher文件。

       那么JarLauncher是什么?

       JarLauncher实际上是一个Jar的启动器,那么它核心作用就是:

加载jar包的jar文件和class文件

       加载完成之后会找到Start-Class指定的启动类,通过反射进行启动应用。

五、为什么Spring Boot要自定义一个ClassLoader

       这个就和java有关系了,对于嵌套的jar,这里有很重要的一句话:

Java没有提供任何标准的方式来加载嵌套的jar文件(即,它们本身包含在jar中的jar文件)。

       所以对于Spring Boot项目中依赖的jar文件,java并无能为力,对于-jar的底层是找到一个Main-Class属性值,对于Spring Boot项目要启动,有两个核心的事情就要去做了:

(1)加载jar中的jar文件以及class文件;

(2)启动main方法;

       对于main方法启动类上的注解@SpringBootApplication注解是在相应的jar中的,很显然不能直接先启动main方法中的类,然后再加载jar文件。

       所以需要Main-Class就不能指向main方法中的启动类了,对于SpringBoot定义了一个JarLauncher来加载jar文件和class文件,对于jar文件和class文件的加载的工作在java中是由classloader来完成的,java内置的classloader不能满足要求,也就需要Spring Boot自定义ClassLoader来搞定这个事情了,也就是JarLauncher是一个自定义的类加载器。

       对于Starter-Class是Spring Boot自己定义的一个属性值,为了JarLauncher加载了jar文件和class文件之后,可以找到启动类。

六、在IDE如何启动Spring boot应用

       在上面只提到在一个fat jar里启动SpringBoot应用的过程,那么IDE里Spring boot是如何启动的呢? 在IDE里,直接运行的Main函数是应用的Main函数:

       在IDE里启动SpringBoot应用是最简单的一种情况,因为依赖的Jar都让IDE放到classpath里了,所以Spring boot 直接启动就完事了。

七、JarLauncher扩展加载说明

(1)JarLauncher通过加载BOOT-INF/classes目录及BOOT-INF/lib目录下jar文件,实现了fat jar的启动。

(2)SpringBoot通过扩展JarFile、JarURLConnection及URLStreamHandler,实现了jar in jar中资源的加载。

(3)SpringBoot通过扩展URLClassLoader–LauncherURLClassLoader,实现了jar in jar中class文件的加载。

       另外一个WarLauncher是:WarLauncher通过加载WEB-INF/classes目录及WEB-INF/lib和WEB-INF/lib-provided目录下的jar文件,实现了war文 件的直接启动及web容器中的启动。

总结

       总结一下Spring Boot应用的启动流程:

(1)Spring Boot应用打包之后,生成一个Fat jar,包含了应用依赖的jar包和Spring Boot loader相关的类。

(2)Fat jar的启动Main函数是JarLauncher,它负责创建一个LaunchedURLClassLoader来加载/lib下面的jar,并以一 个新线程启动应用的Main函数。

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à悟空学院:悟空学院

学院中有Spring Boot相关的课程!!

SpringBoot视频:从零开始学Spring Boot Plus - 网易云课堂

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringSecurity5.0视频:权限管理spring security - 网易云课堂

ShardingJDBC分库分表:分库分表Sharding-JDBC实战 - 网易云课堂

分布式事务解决方案:分布式事务解决方案「手写代码」 - 网易云课堂

JVM内存模型调优实战:深入理解JVM内存模型/调优实战 - 网易云课堂

Spring入门到精通:Spring零基础从入门到精通 - 网易云课堂

大话设计模式之爱你:百度短网址

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟纤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值