Spring Boot项目入口mainClass竟然不是ApplicationRun!

emmmm标题有点今日某条的,其实我想表达的意思是Spring Boot项目打成的jar包,程序的真正入口main方法并不是我们写的ApplicationRun启动类里的。当然,这看怎么理解了,如果非要说这是我自己写的main方法它就是入口这也没错,只不过你这main方法前面人家jar包还有一个自己的入口呢。

先说我是怎么发现这个问题的吧,最近写了一个小应用,当然用Spring Boot开发的,打成jar包后在本地执行没啥问题。然后我想把它发给别人,即使人家电脑上没有jre环境也能执行这个jar包,这就需要连同jar包带着jre一起打包成exe程序了,然后就下载了exe4j一顿操作,具体操作步骤感兴趣的可以去搜一下,然后重点来了。

执行到这一步的时候

这一步是刚刚选好了jar包,准备配置入口mainClass,共有四个选项,本着其他三个没见过Application自己写的比较亲的理由,选了Application,然后又是一顿操作exe文件句生成了,兴奋的运行了一下,哦吼...

咋回事,这不明摆着的还没找到?然后就懵了一会,一度想明天再看。最后把其他三个一个一个试了一下(其实看名字第一个就猜对了,试其它两个为了确认一下),发现下面这个mainClass才是正确的入口选项

 

找到了正确的入口方法,小应用也跑了起来,但是这个问题还在,于是就去了解了一下为什么是这个JarLauncher。 

为什么是JarLauncher这个问题可以有两个回答:

1.简单粗暴直接反编译spring boot的可执行jar,看MANIFEST.MF文件。该文件记录了jar包的一些配置信息,其中就有mainClass,如下图:

文件最后一行白纸黑字写了mainClass是JarLauncher。

2.都知道spring boot是有自己的打包插件spring-boot-maven-plugin的,

这是一个boot自定义的maven插件,其打成的jar又称fat jar,和maven自带的maven-jar-plugin有区别。要想知道为什么入口是JarLauncher那就从源头开始,看看spring boot是如何打包的。于是就反编译了这个自定义打包插件。结构如图:

 文件还是比较少的,之前有了解到spring boot的打包方式其实就是一个repackage重新打包的过程,所以这次源码撸的还算顺利,直接找到了RepackageMojo这个类文件。里面第一个方法就是excute()方法,看来是入口了。

可以看出前两个if检查后核心在repackage()方法,这个方法也是紧跟其后。

这里面东西比较多,Artifact source拿到的是项目唯一标识信息,这个在我们建maven项目的时候有遇到过。File target拿到的是项目源文件,打包嘛,没东西怎么打。需要重点关注的是这个Repackager repackager = getRepackager(source.getFile()),看样子这个repackager应该是个正儿八经的打包工具,东西都拿到后try语句块中调用repackager.repackage()开始打包也能看出来。那就看一下这个getRepackager()方法,是怎么拿到这个打包工具的。

 这里面就是根据项目唯一标识source和layoutFactory样式new了一个Repackage对象。然后有一个setMainClass()。嗯哼这不就是我想找的嘛?兴奋的点了一下这个变量看是怎么来的,结果发现:

打了@Parameter注解 ,看来是从配置文件里来的,忽然想到之前用maven自己的打包插件打包好像确实要指定mainClass,这就很失望了,配置文件里指定的不就是自己写的启动类嘛。源码一顿撸到最后把自己结论推翻了?没有没有还没完,接着又看了看这个layoutFactory,这个layout可以看下有哪几种:

意思就是打包成什么嘛,我们这里肯定是JAR。 然后就想看看这个JAR类是什么,看引用这个类在另一个jar包里。

接着反编译了这个spring-boot-loader-tools,一眼就找到了这个JAR,还找到了刚刚看到的打包工具类Repackager:

 不过我已经对这个打包工具怎么打包已经不感兴趣了,看一下这个JAR:

还是很清晰的,到这里也找到答案了,getLauncherClassName()方法顾名思义返回的是入口类文件路径,返回的就是这个JarLauncher,意思就是jar包的入口就是JarLauncher。同时还在想困惑之前的那个setMainClass(),就想文章开头提到的:

哈哈截了张本文的图,大不了就理解成mainClass(自己写的入口类)和launcherClass(JarLauncher)吧, launcherClass在更外面,这样就清晰多了。

我们的fat jar反编译后可以找到这个JarLauncher:

感兴趣的可以去深究一下。 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是关于Spring Boot项目的一些基本教程: Spring Boot是一个快速构建基于Spring框架的应用程序的工具。它提供了自动配置、约定优于配置等功能,使得开发者可以更快地搭建出一个Spring应用程序。 以下是创建Spring Boot项目的步骤: 1. 确保已经安装好Java JDK和Maven。 2. 打开Eclipse或者IntelliJ IDEA,点击菜单栏的“File” -> “New” -> “Project”。 3. 在“New Project”对话框中,选择“Maven” -> “Maven Project”,并勾选“Create a simple project”复选框,点击“Next”。 4. 在“New Maven Project”对话框中,选择“archetype-quickstart”,并填写Group Id、Artifact Id和Version等信息,然后点击“Finish”。 5. 在pom.xml文件中添加Spring Boot的依赖: ``` <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.6.2</version> </dependency> </dependencies> ``` 6. 创建一个Spring Boot应用程序的入口,添加`@SpringBootApplication`注解,并在main方法中启动Spring Boot应用程序: ``` @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` 7. 编写Controller,处理请求: ``` @RestController public class HelloController { @RequestMapping("/") public String index() { return "Hello, Spring Boot!"; } } ``` 8. 运行应用程序,访问http://localhost:8080/即可看到页面输出“Hello, Spring Boot!”。 这些步骤可以帮助你快速创建一个Spring Boot应用程序。当然,在实际开发过程中,你还需要学习如何使用Spring Boot的各种功能,如自动配置、数据访问、日志记录等。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值