SpringBoot 源码解析2:启动流程1

SpringBoot 源码解析2:启动流程1

    • 1.启动方式
    • 2.@SpringBootApplication
    • 3.SpringApplication
      • 3.1 构造器SpringApplication
      • 3.2 SpringApplication#run
    • 3.3 SpringApplication#run 中关键方法
      • 3.1 SpringApplication#prepareEnvironment
      • 3.2 SpringApplication#prepareContext
      • 3.3 SpringApplication#createApplicationContext
      • 3.4 SpringApplication#prepareContext
      • 3.5 SpringApplication#refreshContext
      • 3.6 SpringApplicationRunListeners#started
      • 3.7 callRunners
      • 3.8 SpringApplicationRunListeners#running

1.启动方式

@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

SpringBoot启动方式,这里就不多做说明了

2.@SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {xxxxx
}
  1. 可以看到SpringBootApplication注解由三个注解标注,@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan。
  2. 简要说明一下这三个注解的作用:
    2.1. SpringBootConfiguration由Configuration标注,而Configuration又是由Component标注,Component表明这个类要被Spring管理。同时Configuration注解还能对当前类进行代理。
    2.2. EnableAutoConfiguration是由@Import注解所标注,而Import注解的作用是告诉Spring容器需要注入哪些bean。
    2.3. ComponentScan是用来配置扫描Component资源的策略,包含策略和剔除策略,剔除策略优先及高。

3.SpringApplication

3.1 构造器SpringApplication

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath();setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();
}
  1. 参数说明:resourceLoader写死null,primarySources为启动类MyApplication。
  2. 通过classLoader判断当前的WebApplicationType,这里返回的是WebApplicationType.SERVLET。
  3. 从spring.factories文件中拿到ApplicationContextInitializer和ApplicationListener。spring.factories文件解析可参考 SpringBoot 基础概念:SpringApplication#getSpringFactoriesInstances
  4. 推断出主类,通过RuntimeException的栈帧信息找到第一个"main"方法所属的类,也就是MyApplication。

3.2 SpringApplication#run

public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);prepareContext(context, environment, listeners, applicationArguments, printedBanner);refreshContext(context);afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}listeners.started(context);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;
}
  1. 这是SpringBoot真正启动的总流程。
  2. 从spring.factories文件中获取SpringApplicationRunListener对应的类,通过参数类型为SpringApplication.class, String[].class的构造器实例化,其中值为当前的SpringApplication对象和启动参数args,封装在SpringApplicationRunListeners里。其实是实例化了EventPublishingRunListener,从名字上可知,它是用来分发事件的。
    在这里插入图片描述
  3. 调用SpringApplicationRunListeners#starting发布"正在启动"事件,事件为ApplicationStartingEvent。
  4. prepareEnvironment方法发布"环境准备"事件,由ConfigFileApplicationListener监听,然后解析配置文件(如yml、bootstrap、properties、xml等),将解析的信息存放到Environment里面。
  5. printBanner方法打印banner
  6. createApplicationContext创建ApplicationContext,判断的依据是webApplicationType。由于是Servlet类型的,创建的是AnnotationConfigServletWebServerApplicationContext。
  7. 获取异常报告事件监听器,在catch到异常监听failed。
  8. 准备applicationContext
  9. refreshContext(context)刷新容器
  10. listeners.started(context) 发布"已启动"事件
  11. 调用ApplicationRunner和CommandLineRunner
  12. listeners.running发送"running事件"

3.3 SpringApplication#run 中关键方法

3.1 SpringApplication#prepareEnvironment

3.2 SpringApplication#prepareContext

3.3 SpringApplication#createApplicationContext

3.4 SpringApplication#prepareContext

3.5 SpringApplication#refreshContext

3.6 SpringApplicationRunListeners#started

3.7 callRunners

3.8 SpringApplicationRunListeners#running

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/279254.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot乐器视频学习网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。你想解决的问题&#xff0c;今天给大家介绍…

全网最详细,Jmeter性能测试-性能基础详解,参数化函数取值(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 参数化详解 Jmete…

MUR8060PT-ASEMI新能源功率器件MUR8060PT

编辑&#xff1a;ll MUR8060PT-ASEMI新能源功率器件MUR8060PT 型号&#xff1a;MUR8060PT 品牌&#xff1a;ASEMI 封装&#xff1a;TO-247 最大平均正向电流&#xff1a;80A 最大重复峰值反向电压&#xff1a;600V 产品引线数量&#xff1a;3 产品内部芯片个数&#xf…

鸿蒙4.0开发 - DevEco Studio如何使用Previewer窗口预览器报错

DevEco Studio预览器概况在HarmonyOS应用开发过程中&#xff0c;通过使用预览器&#xff0c;可以查看应用的UI效果&#xff0c;方便开发者实时查看应用的运行效果&#xff0c;随时调整代码。 1.正常启动 打开预览器的位置在DevEco Studio编辑界面的右上角部分&#xff0c;竖排…

ES-组合与聚合

ES组合查询 1 must 满足两个match才会被命中 GET /mergeindex/_search {"query": {"bool": {"must": [{"match": {"name": "liyong"}},{"match_phrase": {"desc": "liyong"}}]}}…

YOLOv8-Seg改进:轻量化卷积设计 | DualConv双卷积魔改v8结构

🚀🚀🚀本文改进: DualConv双卷积魔改v8结构,达到轻量化的同时并能够实现小幅涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升分割性能…

压缩包文件暴力破解 -Server2005(解析)

任务五十一: 压缩包文件暴力破解 任务环境说明:Server2005 1. 通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机服务版本信息,将 Telnet 版本信息字符串 作为 Flag 提交; flag:Microsoft Windows XP telnetd 2. 通过本地PC中渗透测试平台Kali对服务器场景Windows进行渗透测…

在thinkphp5.1 自定义验证规则 获取get 传递的值的时候 传递了 值 能够获取到 验证出错

控制器: public function teamDetail(){if(request()->isGet()){$team_id $this->request->get(team_id, );$this->validate->scene(teamDetail)->check($team_id);if ($this->validate->getError()) {return resultArray(lang(strval($this->vali…

怎么实现AI数字人7x24小时不间断直播?

随着ai技术的发展 &#xff0c;数字人逐渐占据直播行业&#xff0c;而随着AI数字人直播的兴起,企业又纷纷开始通过部署数字人直播SAAS系统的方式搭建属于自己的数字人直播平台来实现7x24小时不间断直播&#xff0c;增加企业的曝光&#xff0c;以此来打开市场的知名度&#xff0…

软实力篇---第三篇

系列文章目录 文章目录 系列文章目录前言一、专业技能怎么写二、排版注意事项三、其他一些小tips前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、专业技能怎么…

C#教程(三):字符串的各种用法

在C#中&#xff0c;字符串&#xff08;string 类型&#xff09;是一种常用的数据类型&#xff0c;用于存储和操作文本数据。以下是一些C#中字符串的常见用法 1、输出任意的字符串长度 代码 #region 输出任意的字符串长度 Console.WriteLine("请输入你心中想到的名字&…

02-MQ入门之RabbitMQ简单概念说明

二&#xff1a;RabbitMQ 介绍 1.RabbitMQ的概念 RabbitMQ 是一个消息中间件&#xff1a;它接受并转发消息。你可以把它当做一个快递站点&#xff0c;当你要发送一个包裹时&#xff0c;你把你的包裹放到快递站&#xff0c;快递员最终会把你的快递送到收件人那里&#xff0c;按…