boot spring 启动 文本_Spring-Boot启动之前做了哪些事?

原标题:Spring-Boot启动之前做了哪些事?

Spring Boot Jar文件探究

初始化一个Spring 应用,添加如下依赖

执行mvn package命令打包,查看jar包的目录结构

需要使用tree命令,windows下直接使用tree即可,Mac需要安装brew install tree

文件结构比较复杂,解释一下

BOOT-INF/classes: 存放应用编译后的class文件;

BOOT-INF/lib:class path目录, 存放应用依赖的jar包;

META-INF: 存放应用的元信息,如MANIFEST.MF文件;

org:存放Spring Boot自身的class文件;Jar文件的执行器: Spring Boot Loader

我们先从MANIFEST.MF文件查看

里面记录了应用的元信息,Spring的版本,应用的版本,Maven的版本,Main-Class等信息。不难发现,MainClass指向的是org.springframework.boot.loader.JarLauncher(以下简称JarLauncher),而不是我们自己编写的com.fxipp.spring.FirstAppByGuiApplication。

JarLauncher从名字看出是一个jar的执行器,他的class文件位于org.springframework.boot.loader目录下,可见它是Spring自身的class文件。

JarLauncher的GAV org.springframework.boot:spring-boot-loader:2.1.6.RELEASE

通常情况下,他会在spring-boot-starter-parent引入到应用中,既然main-class指向到是JarLauncher,那我们也可以直接执行java org.springframework.boot.loader.JarLauncher,也可以启动Spring项目的。

既然可以执行,那就说明了,JarLauncher这个类才是Spring项目真正的入口。如果我们执行自己写的com.fxipp.spring.FirstAppByGuiApplication会怎么样?

启动报错,原因是找不到org.springframework.boot.SpringApplication这个类,说白了就是没有指定Class Path,Spring Boot应用的Class Path目录是BOOT-INF/lib。

也就是说,JarLauncher可以执行成功,是因为Spring Boot知道了Class Path的路径,说明JarLauncher在启动调用com.fxipp.spring.FirstAppByGuiApplication之前,指定了Class Path的位置。

JarLauncher的代码如下

Archive.Entry:这个类对对象,代表jar包中的资源文件。

isNestedArchive方法判断entry对象是不是位于jar包内,如果在jar内部,返回true。如果不在jar包里面,也就是我们解压了jar包,直接java org.springframework.boot.loader.JarLauncher启动的情况,则返回false。重点看launch(String[])方法

这个方法一共3步

扩展JAR协议

JDK默认支持file、http、jar等协议,所以JDK内部有默认的实现,位于sun.net.www.protocol包下。

JarFile.registerUrlProtocolHandler();这个方法将org.springframework.boot.loader包下对应的JAR协议实现,覆盖原有的JAR实现。

因为原有的JAR实现,ClassPath是我们自己配置环境变量的时候制定的,不是BOOT-INF/lib。创建一个classloader,用于加载JarLauncher类,因为jar包可能会被解压,解压前和解压后的的ClassLoader是不同的。

调用launch方法,将参数传递。

args是我们自己指定的参数。

getMainClass()是获取MANIFEST.MF文件里面Statr-Class属性,也就是获取我们自定义主类的Class 文件地址。

传递推出的类加载器launch方法

launch方法分析:

将ClassLoader放入当前线程里面的ClassLoader里面

创建MainMethodRunner对象,调用里面的run()方法。

run()方法先获取到之前设定的ClassLoader。

利用ClassLoader加载Start-Class之类的类,也就是我们自己的主类。

获取主类里面的main方法,通过反射执行。总结

通过分析,我们可以看出,Spring Boot Loader在调用我们自己的主类之前,主要做了三件事

扩展JDK默认的支持JAR对应的协议,因为Spring Boot启动不仅仅需要JDK半身的JAR文件,还需要BOOT-INF/lib这个目录下的文件。默认实现无法将BOOT-INF/lib这个目录当作ClassPath,故需要替换实现。

判断当前的介质,是java -jar启动,还是java org.springframework.boot.loader.JarLauncher启动。以便获取对应的ClassLoader。

获取MANIFEST.MF文件中的Start-Class属性,也就是我们自定义的主类。通过第二步获取的ClassLoader加载获取到Class文件,通过反射调用main方法,启动应用。返回搜狐,查看更多

责任编辑:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值