SpringApplication.run做了哪些事情

URL

https://mp.weixin.qq.com/s/uP4seo__qYMJMzmbWyUUnA?tdsourcetag=s_pctim_aiomsg

SpringApplication.run
  • 总共做了两件事情,如下源码
    • 穿件SpringApplication对象
    • 利用创建好的对象调用run方法
// SpringApplication.run(Application.class, args);进入 --- 1
public static ConfigurableApplicationContext run(Object source, String... args) {return run(new Object[] { source }, args);}//以上run 方法进去
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {return new SpringApplication(sources).run(args);}
  • 此处开始分成两个部分,一部分:SpringApplication(sources)进行SpringApplication的初始化工作,包括各种配置的初始化,listener初始化等 二部分:run(args)执行run方法启动
//初始化开始
public SpringApplication(Object... sources) {initialize(sources);}
//initialize 方法
private void initialize(Object[] sources) {if (sources != null && sources.length > 0) {// ------1this.sources.addAll(Arrays.asList(sources));}// ----------2this.webEnvironment = deduceWebEnvironment();//--------3setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//-----------4setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//----------5this.mainApplicationClass = deduceMainApplicationClass();}//deduceMainApplicationClass 代码
private Class<?> deduceMainApplicationClass() {try {StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())) {return Class.forName(stackTraceElement.getClassName());}}}catch (ClassNotFoundException ex) {// Swallow and continue}return null;}
  • 在初始化步骤中
    • 步骤1 保存主配置信息
    • 步骤2 判断当前是否是web应用
    • 步骤3中可以看到方法getSpringFactoriesInstances作用在于通过到路径META_INF/spring.factories配置中所有ApplicationContextinitializer配置信息的list,接着通过initializers 将配置信息保存
    • 步骤4 中同步骤3 一致,只不过这次获取的配置类型不同,连调用的方法都是一样的,这次获取的是ApplicationListener类型的配置,之后保存
    • 步骤5 中的deduceMainApplicationClass 方法在寻址一个包含main方法的配置类,如上部分代码,也就是我们自己写的启动类
  • 第二部分则是运行对应的run方法:
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;FailureAnalyzers analyzers = null;configureHeadlessProperty();//-----------1SpringApplicationRunListeners listeners = getRunListeners(args);//-----------2listeners.starting();try {//----------3ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// ----------4ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);//--------5Banner printedBanner = printBanner(environment);//----------6context = createApplicationContext();analyzers = new FailureAnalyzers(context);//---7prepareContext(context, environment, listeners, applicationArguments,printedBanner);//---8refreshContext(context);// -----------9afterRefresh(context, applicationArguments);//--------10listeners.finished(context, null);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// --------11return context;}catch (Throwable ex) {handleRunFailure(context, listeners, analyzers, ex);throw new IllegalStateException(ex);}}// 4步骤中流程:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environmentConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());listeners.environmentPrepared(environment);if (!this.webEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}return environment;}
  • run方法解析:
  1. 此处先调用getRunListeners方法,同之前一样,是获取META_INF/Spring.factories文件中的配置信息,配置信息类型是:SpringApplicationRunListeners
  2. 在得到对应的配置信息后,调用gstarting方法,改方法会去循环调用刚才获取到的所有配置,并且触发SpringApplicationRunListener中的starting事件,并且是异步的形式触发
  3. 接着封装我们的命令行参数,也就是我们main方法中传入的args参数封装成对应的ApplicationArguments,
  4. 此处步骤会先准备对应环境,主要是我们在配置的配置信息的驾照,在完成环境准备之后在listeners.environmentPrepared(environment); 方法中会回调SpringApplicationRunListener中的environmentPrepared 事件,也是同样的异步的方式触发
  5. 这个步骤pringBanner,启动时候banner的打印,可以自定义自步骤中的图形
  6. createApplicationContext方法会更具我们之前环境判断信来是web环境还是其他决定创建web还是普通的IOC容器
  7. 此步骤中有多个功能
    1. 将environment上下文环境信息保存早ioc容器中
    2. 执行applyInitializers 方法,改方法会遍历之前保存的ApplicationContextInitializer的initialize()事件
    3. 在contextPerpared中遍历SpringApplicationRunListener中的ContextPrepared()事件
    4. 最后在contextLoaded方法中回调SpringApplicationRunListener中的ContextLoaded()事件
  8. refreshContext顾名思义,刷新容器,进行组件的扫描创建,加载等
  9. afterRefresh从IOC容器中获取所有ApplicationRunner和CommandLineRunner遍历所有runner并且调用callRunner方法回调用,先调用ApplicationRunner,在调用CommandLineRunner
  10. finished方法中遍历SpringApplicationRunListener中的finished()事件
  11. 最后返回context ioc容器
总结
  • SpringApplication.run一共做了两件事,一件是创建SpringApplication对象,在该对象初始化时,找到配置的事件监听器,并保存起来.第二件事就是运行run方法,此时会将刚才保存的事件监听器根据当前时机触发不同的事件,比如容器初始化,容器创建完成等.同时也会刷新IoC容器,进行组件的扫描、创建、加载等工作.

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

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

相关文章

C++ class实现Huffman树(完整代码)

代码如下: #include <iostream> #include <string> using namespace std; const unsigned int n 8;//字符数NUM&#xff0c;这里的字符数为8 const unsigned int m 2 * n - 1;//结点总数 const float MAX 1e8;class HTNode {friend class HuffmanTree; private…

二叉树的遍历(堆栈)

二叉树的遍历&#xff08;堆栈&#xff09; 如何理解用堆栈方式代替递归去遍历二叉树&#xff0c;关键点在于了解每个结点输出时的顺序&#xff0c;以及理解前序中序后序是如何遍历的&#xff0c;这点很重要&#xff0c;可以自己画一个树图&#xff0c;熟练写出遍历的结果 以…

ASP.NET Core分布式项目实战(第三方ClientCredential模式调用)--学习笔记

任务10&#xff1a;第三方ClientCredential模式调用创建一个控制台程序dotnet new console --name ThirdPartyDemo添加 Nuget 包&#xff1a;IdentityModel添加之后还原dotnet restoreClientusing System; using System.Net.Http; using System.Threading.Tasks; using Identit…

Hystrix能解决的问题

Hystrix 问题产生 雪崩效应&#xff1a; 一种因为服务提供者的不可用导致服务调用者不可用&#xff0c;并将不可用情况逐渐放大的过程 形成过程&#xff1a; 服务提供者不可用&#xff1a; 硬件故障&#xff0c;硬件损坏&#xff0c;服务器宕机&#xff0c;网络硬件故障&…

C++ class实现邻接矩阵存储的图(完整代码)

代码如下: #include <iostream> #include <queue> using namespace std; typedef int VertexType; typedef int EdgeType; const int MaxVertexNum 30;class MGraph { public:MGraph(){CreatGraph();};void CreatGraph();void Visit(int v);void BFS(int v);void…

二叉搜索树(创建,插入,删除):基础篇,适合新手观看。

1.1 二叉搜索树的插入 二叉搜索树的概念相信大家都很清楚&#xff0c;无非就是左小右大 创建二叉搜索树&#xff0c;其实就是多次调用二叉搜索树的插入方法&#xff0c;所以首先我们来讲讲如何插入节点到二叉搜索树里&#xff0c;假设一颗二叉搜索树如下&#xff0c;现在要插入…

.NET 的过去、现在和未来

作为一名使用了十多年.NET 开发平台的开发者来说&#xff0c;多年来笔者鲜少在各类博客媒体推广布道 .NET平台&#xff0c;但也默默地关注着 .NET 平台的发展变化&#xff0c;为每一次新技术的出现欢呼&#xff0c;为近年来 .NET 的沉默感到惋惜&#xff0c;也为开放开源的 .NE…

Redis数据结构以及对应存储策略

redis数据结构&#xff1a; String 可以是字符串也可以是数字&#xff0c;以及浮点数List&#xff0c;一个链表&#xff0c;链表上每一个节点都包含一个字符串set 包含字符串的无序手机其&#xff0c;特点是每一个字符都是唯一的hash&#xff0c;包含键值对的无序散列&#xf…

AVL树(平衡二叉树)讲解,入门篇,适合新手观看

1.1 概念 平衡二叉树就是为了让二叉搜索树的平均查找长度更短&#xff0c;时间复杂度更靠近logN,如果一个二叉搜索树不平衡了就会出现图1情况&#xff0c;完全变成一个数组&#xff0c;时间复杂度也变为了O(N)。 平衡因子&#xff1a;平衡因子就是针对于树中某一结点&#xff…

读源码,对开发者重要吗?

.NET 5.0 Peview 2发布4月2日&#xff0c;微软发布了.NET 5.0 Preview 2&#xff0c;带来功能和性能方面的改进。这一版本包括.NET 5.0.0 Preview 2与.NET SDK 5.0.100 Preview 2。.NET 5是.NET Framework和.NET Core的未来&#xff0c;最终将成为一个统一平台&#xff0c;.NET…

Redis和DB数据一致性解决方案

问题出现原因 并发时候无法保证读写的先后顺序&#xff0c;如果删掉了缓存还没来得及写库&#xff0c;另外一个县城就多来读取&#xff0c;发现缓存为空就去读取数据库并且写入缓存&#xff0c;这时候缓存中就是脏数据如果先写库&#xff0c;在删除缓存前&#xff0c;写库的线…

数据结构堆的时间复杂度(最大堆,最小堆)

创建堆的方式有两种&#xff0c;一种是一边插入结点&#xff0c;一边调用堆的插入方法调整堆&#xff0c;这样的时间复杂度就是 O(NlogN)&#xff0c;而第二种方式就把时间复杂度缩减到了O(N)&#xff0c;它是采用先把结点插入好了&#xff0c;然后再来调整堆&#xff0c;并不是…

中国速度之二神山建设(3):有力的技术保障,基建世界里的云原生缩影 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩丰…

Rx2.0后台开发分享

Rxjava2.x 微软的一个函数库&#xff0c;Rx是一个编程模型&#xff0c;模板是提供一致的编程接口&#xff0c;帮助开发者更方便的处理异步数据流&#xff0c;现在Rx已经支持几乎全部的流行编程语言。比较流行的有Rxjava&#xff0c;RxJs&#xff0c;Rx.NET&#xff0c;社区网站…

中国速度之二神山建设(4):全能运维,召之即来,来之即战 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩丰…

JAVA两类比较器的区别(Comparable,Comparator)

内部比较器Comparable 一个类实现了Comparable接口&#xff0c;那么它就有了一个内部比较器&#xff0c;实现了Comparable的类可以调用Collections工具类或Arrays的sort方法进行比较 外部比较器Comparator 一个类实现了Comparator接口&#xff0c;那么它就是一个外部比较器&…

Spring Cloud部分源码分析Eureka,Ribbon,Feign,Zuul

Eureka SpringCloud Eureka使用NetFlix Eureka来实现的&#xff0c;它包括了服务端组件和客户端组件&#xff0c;并且都是用java 编写的。 Eureka服务端就是服务注册中心&#xff0c;Eureka客户端主要处理服务的注册发现&#xff0c;通过注解和参数配置的方式&#xff0c;客户…

C++ class实现邻接表存储的图(完整代码)

代码如下: #include <iostream> #include <queue>using namespace std; const int MaxVertexNum 30; typedef int InfoType; typedef int VertexType;class Node {friend class VNode;friend class ALGraph; private:int adjvertex;InfoType info;Node *next; };…

世界上首个被数学证明安全的OS微内核seL4成立基金会

Linux 基金会正在与澳大利亚国家科学机构 CSIRO 合作&#xff0c;打造 seL4 操作系统微内核生态。近日 Linux 基金会宣布托管 seL4 基金会&#xff0c;该基金会以澳大利亚国家科学机构 CSIRO 的数字机构 Data61 创建的 seL4 操作系统微内核为基础项目。seL4 是一个安全操作系统…

数据结构(哈夫曼树,哈夫曼编码)入门篇,JAVA实现

什么是哈夫曼树 哈夫曼树就是一种最优判定树&#xff0c;举个例子&#xff0c;如下一个判断逻辑 if(s<60) g1; else if(s<70) g2 else if(s<80) g3 else if(s<90) g4 else g5; 分数概率图如下 如果按照代码从上到下顺序构造判定树&#xff0c;那么如下图所示&am…