全站资源开放下载,感谢广大网友的支持
链接失效请移步职业司平台
非盈利平台

非盈利平台

只为分享一些优质内容

Java帮帮-微信公众号

Java帮帮-微信公众号

将分享做到极致

微信小程序

微信小程序

更方便的阅读

职业司微信公众号

职业司微信公众号

实时动态通知

安卓APP

安卓APP

我们从此不分开

程序员生活志-公众号

程序员生活志-公众号

程序员生活学习圈,互联网八卦黑料

支付宝赞助-Java帮帮社区
微信赞助-Java帮帮社区

SpringBoot启动过程分析

104
发表时间:2018-11-26 11:39


   本文主要分析 SpringBoot 的启动过程。

   SpringBoot的版本为:2.1.0 release,最新版本。

一.时序图

   还是老套路,先把分析过程的时序图摆出来:时序图-SpringBoot2.10启动分析

二.源码分析

   首先从我们的一个SpringBoot Demo开始,这里使用 SPRING INITIALIZR 网站生成的starter开始的:

   经过SpringApplication多个重载的构造方法,最后到达:

   看一眼,WebApplicationType#deduceFromClasspath ,deduce意为推断,即根据classpath下的内容推断出应用的类型。实现是通过ClassUtils#isPresent来尝试加载代表不同应用类型特征的Class文件:

   SpringApplication#getSpringFactoriesInstances,从类路径下 META-INF/spring.factories 下加载 SpringFactory 实例,类似的操作在 Dubbo SPI中也有:

   SpringFactoriesLoader#loadFactoryNames,加载工厂名字:

   继续捉迷藏,到了 SpringFactoriesLoader#loadSpringFactories:下面的内容就是找到所有classpath下的 spring.factories 文件,读取里面的内容,放到缓存中,此处和Dubbo SPI中ExtensionLoader#loadDirectory几乎是一模一样,可以参考我写过的 Dubbo源码 里面的注释。

   我们也来看一下上面读取的文件 spring.factories 的内容,大概长这个样子:

   是时候跳出来了,回到主线,返回实例化对象后,到了 SpringApplication#deduceMainApplicationClass,获取程序当前运行堆栈,看现在运行的是哪个类的 main 方法,然后保存到上下文:

   至此,SpringApplication的构造函数的分析完成,后面我们继续分析SpringApplication的run()方法中做了哪些操作。

SpringBoot的版本为:2.1.0 release,最新版本。

一.时序图

   一样的,我们先把时序图贴上来,方便理解:

二.源码分析

   回顾一下,前面我们分析到了下面这步:

   SpringApplication#run方法的内容较多,准备刷屏了:

   上面从大体上介绍了SpringApplication在run()中做的事情,下面详细分析每步具体的操作。

   SpringApplication#getRunListeners,获取所有启动监听器,一样的套路,通过SPI机制,通过工厂创建SpringApplicationRunListener的实例:

   从 spring.factories 里面找到如下内容:也就是最后拿到SpringApplicationRunListener的实例是EventPublishingRunListener的对象。

   SpringApplication#configureHeadlessProperty,设置系统属性 "java.awt.headless" 。headless是系统的一种配置模式,在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式,也就是告诉服务器,没有这些硬件设施,当需要这是设备信息的时候,别慌,我可以使用awt组件通过计算模拟出这些外设的特性。

   SpringApplication#prepareEnvironment,准备应用上下文 environment 对象,像设置当前使用的配置文件profile,就在该方法内完成:

   SpringApplication#configureEnvironment,添加 ConversionService 转换器,保存启动参数,即最外面main的入参args数组:

   SpringApplication#configureProfiles ,设置当前运行环境的配置文件,会去查看"spring.profiles.active"中指定的是什么:

   不小心有陷入进去了,再次回到run()。

   接着看后面是获取Banner。根据环境找到Banner,默认找classpath下面的 banner.txt,Gitee上面很多管理系统打印出各种自定义名称。实现很简单,只要你提前制作好banner.txt,放到resources下面,启动的时候,就会加载你的,覆盖原始的Banner信息。这部分代码比较简单,只要跟进去看下就能看明白,考虑篇幅问题,省略过了。分享一个在线设计Banner.txt的网站

   如果需要关闭Banner输出,在App里面调用:

SpringApplication.setBannerMode(Banner.Mode.OFF);// 关掉Banner

   接下来重点看一下 SpringApplication#prepareContext,分析SpringBoot如何准备上下文的:

   稳住,快启动完了。接着看SpringApplication#refreshContext,完成刷新上下文的操作:

   然后是到了SpringApplication#afterRefresh,这是一个模板方法,父类不提供实现,留给子类发挥想象实现,在context刷新好之后需要做的事情可以在此方法实现中完成。

   最后就是 stopWatch.stop() 停止计时,打印启动耗时信息,回调监听器的started(ctx)方法,返回上下文context。

   至此,SpringBoot启动过程分析完成。


Java帮帮学习群生态

Java帮帮学习群生态

总有一款能帮到你

Java学习群

Java学习群

与大牛一起交流

大数据学习群

大数据学习群

在数据中成长

九点编程学习群

九点编程学习群

深夜九点学编程

python学习群

python学习群

人工智能,爬虫

测试学习群

测试学习群

感受测试的魅力

Java帮帮生态承诺

Java帮帮生态承诺

一直坚守,不负重望

初心
勤俭
诚信
正义
分享
友链交换:加帮主QQ2524138991 留言即可 24小时内答复  
业司
满吉教育资讯
会员登录
获取验证码
登录
登录
我的资料
留言
回到顶部