趣文网 > 作文大全

springboot的jar为何能独立运行

2020-12-02 04:30:02
相关推荐

能独立运行的jar文件

在开发springboot应用时,通过java -jar命令启动应用是常用的方式,今天就来一起了解这个简单操作背后的技术;

开发demo

开发一个springboot应用作为本次研究的对象,对应的版本信息如下:

JDK:1.8.0_211springboot:2.3.1.RELEASEmaven:3.6.0接下来开发springboot应用,这个应用异常简单:

springboot应用名为springbootstarterdemo,pom.xml文件内容:

2. 只有一个java类,里面有个http接口:

3. 编码完成,在pom.xml所在目录执行命令

mvn clean package -U -DskipTests

4. 构建成功后,在target目录下得到文件springbootstarterdemo-0.0.1-SNAPSHOT.jar

5. 就是这个springbootstarterdemo-0.0.1-SNAPSHOT.jar,此时执行java -jar springbootstarterdemo-0.0.1-SNAPSHOT.jar就能启动应用,如下图:

接下来就用这个springbootstarterdemo-0.0.1-SNAPSHOT.jar来分析jar文件能够独立启动的原因;

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文件名(本例中是springbootstarterdemo-0.0.1-SNAPSHOT.jar);该jar文件中包含的是class和资源文件;在manifest文件中有Main-Class的定义;Main-Class的源码中指定了整个应用的启动类;(in its source code)小结一下:java -jar会去找jar中的manifest文件,在那里面找到真正的启动类;探查springbootstarterdemo-0.0.1-SNAPSHOT.jar

springbootstarterdemo-0.0.1-SNAPSHOT.jar是前面的springboot工程的构建结果,是个压缩包,用常见的压缩工具就能解压,我这里的环境是MacBook Pro,用unzip即可解压;解压后有很多内容,我们先关注manifest相关的,下图红框中就是manifest文件:

3. 打开上图红框中的文件,内容如下:

4. 在上述内容可见Main-Class的值org.springframework.boot.loader.JarLauncher,这个和前面的java官方文档对应上了,正是这个JarLauncher类的代码中指定了真正的启动类;

疑惑出现

在MANIFEST.MF文件中有这么一行内容:Start-Class: com.bolingcavalry.springbootstarterdemo.Springbootstarter demoApplication

2. 前面的java官方文档中,只提到过Main-Class ,并没有提到Start-Class;

3. Start-Class的值是SpringbootstarterdemoApplication,这是我们的java代码中的唯一类,也只真正的应用启动类;

4. 所以问题就来了:理论上看,执行java -jar命令时JarLauncher类会被执行,但实际上是SpringbootstarterdemoApplication被执行了,这其中发生了什么呢?

猜测

动手之前先猜一下,个人觉得原因应该如下:

java -jar命令会启动JarLauncher;Start-Class是给JarLauncher用的;JarLauncher根据Start-Class找到了SpringbootstarterdemoApplication,然后执行它;分析JarLauncher

先下载SpringBoot源码,我下载的是2.3.1版本;JarLauncher所在的工程是spring-boot-loader,先弄明白JarLauncher的继承关系,如下图,可见JarLauncher继承自ExecutableArchiveLauncher,而ExecutableArchiveLauncher的父类Launcher位于最顶层,是个抽象类:

3. java -jar执行的是JarLauncher的main方法,如下,会实例化一个JarLauncher对象,然后执行其launch方法,并且将所有入参都带入:

publicstaticvoidmain(String[] args)throws Exception { new JarLauncher().launch(args);}

4. 上面的launch方法在父类Launcher中:

5. 可见要重点关注的是getMainClass()方法,在看这个方法之前,我们先去关注一个重要的成员变量archive,是JarLauncher的父类ExecutableArchiveLauncher的archive,如下可见,该变量又来自方法createArchive:

6. 方法来自Launcher.createArchive,如下所示,可见成员变量archive实际上是个JarFileArchive对象:

7. 现在回到getMainClass()方法,可见his.archive.getManifest方法返回的是META-INF/MANIFEST.MF文件的内容,然后getValue(START_CLASS_ATTRIBUTE)方法实际上就是从META-INF/MANIFEST.MF中取得了Start-Class的属性:

8. 从上述分析可知:getMainClass()方法返回的是META-INF/MANIFEST.MF中取得了Start-Class的属性com.bolingcavalry.springbootstarterdemo.SpringbootstarterdemoApplication,再次回到launch方法中,可见最终运行的代码是launch(args, launchClass, classLoader),它的launchClass参数就是com.bolingcavalry.springbootstarterdemo.SpringbootstarterdemoApplication:

9. 展开launch(args, launchClass, classLoader),最终查到了MainMethodRunner类:

终于,真相大白了;

小结

最后尽可能简短做个小结,先看jar是如何产生的,如下图,maven插件生成的jar文件中,有常见的class、jar,也有符合java规范的MANIFEST.MF文件,并且,还在MANIFEST.MF文件中额外生成了名为Start-Class的配置,这里面是我们编写的应用启动类SpringbootstarterdemoApplication:

启动类是JarLauncher,它是如何与MANIFEST.MF文件关联的呢?从下图可以看出,最终是通过JarFile类的成员变量manifestSupplier关联上的:

再来看看关键代码的执行情况,如下图:

至此,SpringBoot的jar独立运行的基本原理已经清楚,探究的过程中,除了熟悉关键代码流程,还对jar中的文件有了更多了解,如果您正在学习SpringBoot,希望本文能给您一些参考;

官方文档

最后附上SpringBoot官方文档,可以看到Start-Class描述信息:

2. 上述文档明确提到:Start-Class定义的是实际的启动类,此时的您应该对一切都了然于胸,产生本该如此的感慨;

想了解更多精彩内容,快来关注计算机java编程

阅读剩余内容
网友评论
显示评论内容(2) 收起评论内容
  1. 2021-12-16 11:41瑾瑜丶匿瑕[火星网友]IP:762481471
    SpringBoot的自动配置和约定优于配置的特性让jar包可以独立运行,省去了很多配置的烦恼。
    顶4踩0
  2. 2020-10-21 16:44宁馨儿[辽宁省网友]IP:3406516930
    因为SpringBoot内置了嵌入式的Servlet容器,不需要外部依赖,非常方便。
    顶0踩0
相关内容
延伸阅读
小编推荐

大家都在看

写父母的英语作文 我来到了新学校作文 水果节作文500字 东京奥运会作文 英语作文中的万能句 雪的联想作文 小鸭子爬楼梯作文 小金鱼作文一年级 语文作文优美句子 选择信念作文500字 美丽的乌兰察布市作文300 高考作文点评 写南山公园的作文 什么什么真好作文600字 关于感动的作文题记 制作文字壁纸 冬天的作文250字 让我后悔的一件事作文300字 环保作文结尾 初中英语万能作文 关于体操比赛的作文 现在的自己作文 第一次坐高铁作文 那件事真让我开心作文 植树作文600字初中 原来我也很棒作文 我的梦想作文三年级 队列比赛作文400字 庆国庆 作文 高考满分作文开头