1. 引言

SpringBoot项目中的启动类,一般都是XXApplication,例如StatsApplication,UnionApplication。

每个项目的启动类名称都不一样。

但是它的启动类真的是XXApplication吗?

2. META-INF/Manifest.mf文件

jar文件实际上是class文件的zip压缩存档。jar并不能表达应用程序的便签信息.

META-INF/Manifest.mf文件提供存档的便签信息,Manifest.mf有 Main-Class,用来标明jar文件的入口类。

解压jar包,查看META-INF/Manifest.mf过程如下:

重要信息如下

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.shanyuan.StatsApplication

也就是说:org.springframework.boot.loader.JarLauncher 才是 Spring Boot 的启动类!

不熟悉 Spring Boot 的可以看下这个仓库:https://github.com/javastacks/spring-boot-best-practice

下面浏览下JarLauncher

3. 浏览JarLauncher

3.1 找到JarLauncher

进入IDEA,Ctrl+N查找JarLauncher,竟然找不到!!

进入 https://search.maven.org/classic/#advancedsearch 查询JarLauncher

在查询结果找到spring下的项目

确定JarLauncher位于spring-boot-loader下。为了方便查看源码,在pom中引入

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-loader</artifactId><scope>provided</scope>
</dependency>

3.2.JarLauncher说明

JarLauncher作为引导类 ,当调用java -jar 命令时,将调用main方法,实际上调用的是 JarLauncher#launch方法,该方法继承与org.springframework.boot.loader.Launcher

简化层次关系为:

JarLauncher#launch代码如下

protected void launch(String[] args) throws Exception {JarFile.registerUrlProtocolHandler();ClassLoader classLoader = createClassLoader(getClassPathArchives());launch(args, getMainClass(), classLoader);
}

聚句解析

1,.JarFile.registerUrlProtocolHandler();

Spring Boot生成的FAT jar,在被java -jar 引导时,其内部的jar文件无法被sun.net. www.protocol .jar.Handler处理。

所以SpringBoot实现了,org.springframework.boot.loader.jar.Handler

JarFile.registerUrlProtocolHandler(),就注册 org.springframework.boot.loader.jar.Handler

2,ClassLoader classLoader = createClassLoader(getClassPathArchives());

创建ClassLoader。

getClassPathArchives 核心判断是 isNestedArchive方法。

isNestedArchive被JarLauncher覆写了。

其实现如下:

static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";static final String BOOT_INF_LIB = "BOOT-INF/lib/";
@Override
protected boolean isNestedArchive(Archive.Entry entry) {if (entry.isDirectory()) {return entry.getName().equals(BOOT_INF_CLASSES);}return entry.getName().startsWith(BOOT_INF_LIB);
}

也就是说,只要 满足以BOOT-INF/classes/和BOOT-INF/lib/都是classLoader加载的范围。

解压的jar,查看也与只对应

3. launch(args, getMainClass(), classLoader);

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

查看createMainMethodRunner的run方法,如下:

public class MainMethodRunner {// 省略部分代码public void run() throws Exception {Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);mainMethod.invoke(null, new Object[] { this.args });}
}

其中mainClass,来自/META-INF/MANIFEST.MF中的Start-Class属性。

即,JarLauncher是同进程内,通过反射调用Start-Class对应类,即XXXApplication的main方法。

4.总结

Spring Boot 项目的实际启动类是org.springframework.boot.loader.JarLauncher。

在JarLauncher内部通过反射调用XXApplication类的main方法。

具体实现位于 MainMethodRunner中。最后,关于 Spring Boot 系列教程可以关注公众号互联网架构师获取阅读。

作者:温安适
来源:https://my.oschina.net/floor/blog/4301613

关微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBook发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别

9、2T架构师学习资料干货分享

Spring Boot 启动类真的是XXApplication?相关推荐

  1. spring boot 启动类

    做项目用到spring boot 感觉spring boot用起来比较流畅.想总结一下,别的不多说,从入口开始. spring boot启动类Application.class 不能直接放在main/ ...

  2. spring boot启动类启动 错误: 找不到或无法加载主类 xxx.xxxx.Application 的解决方法

    spring boot启动类启动 错误: 找不到或无法加载主类 xxx.xxxx.Application 的解决方法 导入的一个外部的spring boot项目,运行启动类,忽然提示找不到或者无法加载 ...

  3. 介绍一下Spring Boot启动流程以及生命周期勾子函数?

    代码那些事儿 2020-02-22 16:10:15 上篇文章介绍了Spring Boot自动配置的原理,但是对于Spring Boot应用的整个启动流程还是一头雾水,虽然Spring Boot大大简 ...

  4. Spring boot 启动后执行特定的操作

    有时候我们需要在应用启动完成后执行一些特定的操作,比如: 删除一些临时文件或者Redis中的缓存 将一些字典类的数据加载到缓存,这样就不用每次去数据库中查了,有些关联数据从缓存中取得赋值就可以了,不再 ...

  5. Spring Boot启动过程源码分析--转

    https://blog.csdn.net/dm_vincent/article/details/76735888 关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Sp ...

  6. Spring Boot 启动载入数据 CommandLineRunner

    Spring Boot 启动载入数据 CommandLineRunner 实际应用中,我们会有在项目服务启动的时候就去载入一些数据或做一些事情这种需求. 为了解决这种问题.Spring Boot 为我 ...

  7. 在Spring Boot启动时运行代码

    Spring Boot会自动为我们执行很多配置,但是迟早您将不得不做一些自定义工作. 在本文中,您将学习如何进入应用程序引导生命周期并在Spring Boot启动时执行代码 . 因此,让我们看看该框架 ...

  8. Spring Boot————Spring Boot启动流程分析

    一.引言 Spring Boot 的启动虽然仅仅是执行了一个main方法,但实际上,运行流程还是比较复杂的,其中包含几个非常重要的事件回调机制.在实际生产开发中,有时候也会利用这些启动流程中的回调机制 ...

  9. 强大的Spring Boot启动监听器事件-初始化系统账号密码

    文章目录 前言 一.SpringApplicationEvents 事件类型 1.1 ApplicationStartingEvent 1.2 ApplicationEnvironmentPrepar ...

  10. [Spring Boot] 2. Spring Boot 启动过程定制化

    在上一篇文章中,从源码角度介绍了Spring Boot的启动过程.启动的代码虽然只有短短的一行,但是背后所做的工作还真不少,其中有一些可以定制化的部分,主要分为以下几个方面: 初始化器(Initial ...

最新文章

  1. 基因组组装的那些困扰,用单倍体基因组一一破解!
  2. 如何只使用预训练模型的卷积层
  3. 知乎嵌入式大杂烩:学习STM32的一点经验分享
  4. 人社部:截至三季度9757亿元养老保险基金到账运营
  5. Redis 注册为 widows 服务
  6. 广州驾考科目三电子考16日全面启动
  7. [论文泛读] Dynamic placement of virtual machines for managing sla violations (IM, 2007)
  8. python百度文库源码_Python源码剖析3
  9. 水晶报表基本使用方法
  10. Word 2010如何对论文中参考文献进行标注
  11. 【LG-P5072 [Ynoi2015]】盼君勿忘
  12. 论文查找ICCV ECCV CVPR
  13. 工业设计公司如何选择
  14. 瑞士酒店管理大学计算机专业,瑞士DCT国际酒店管理学院生活费用详细介绍
  15. oppo手机android通知关闭,oppo手机怎么关闭系统升级提醒?OPPO关闭系统升级提醒的方法...
  16. 搭建传奇游戏,都需要准备什么东西。
  17. OpenStack 裸金属
  18. 业务系统成功微服务化改造的实施步骤
  19. Python实验--线性回归+梯度下降预测波士顿房价
  20. 毕业半年,买了一台MacBook Pro

热门文章

  1. centos7系统搭建DNS服务器
  2. 算法(0)—— 打造一个C开发库
  3. 基于ExoPlayer的ExoPlayerVideoView
  4. htmlspecialchars_decode 与 html_entity_decode
  5. python脚本:检测字符串标识符
  6. 安装Homebrew是报错,安装不成功(亲测使用,确实解决了问题)
  7. Git版本管理工具Tower for Mac
  8. 如何为自定义域使用我自己的SSL证书?
  9. 如何设置NeoFinder在共享网络中的目录数据库
  10. Transaction事务