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容器,进行组件的扫描、创建、加载等工作.

SpringApplication.run做了哪些事情相关推荐

  1. c语言程序执行完main函数后,一个c程序在执行main函数之前和main之后都做了那些事情啊该如何解决...

    当前位置:我的异常网» C语言 » 一个c程序在执行main函数之前和main之后都做了那些 一个c程序在执行main函数之前和main之后都做了那些事情啊该如何解决 www.myexceptions ...

  2. SpringApplication.run(MyApplication.class, args)运行流程源码分析

    目录 SpringApplication.run(MyApplication.class, args);如何启动springBoot项目的 run() ConfigurableApplicationC ...

  3. java什么时会出现gc_面试题:java GC发生在会么时候,对什么东西,做了什么事情...

    转自cy609329119的 面试题:"你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?" 面试题目: 地球人都知道,Java有个东西叫垃圾收集器,它让创建的对 ...

  4. 无人车巨头每天都在做相同的事情:不惜血本做高精地图是为何?

    来源:腾讯科技 摘要:很多人都关注无人车的发展,殊不知无人车技术中,有十分重要的一环,是无人车的高精地图. 高精地图成为无人车竞赛中的关键一环 目前,很多家无人驾驶公司都在做着同样的事情:绘制同一个路 ...

  5. 【转】做正确的事情,等着被开除(Do the right thing, Wait to get fired)

    原作者博客:https://brendansterne.com/2013/07/11/do-the-right-thing-wait-to-get-fired/ 下面是中文翻译: 我偶然在< T ...

  6. 从任务到可视化,如何理解LSTM网络中的神经元 By 机器之心2017年7月03日 14:29 对人类而言,转写是一件相对容易并且可解释的任务,所以它比较适合用来解释神经网络做了哪些事情,以及神经网

    从任务到可视化,如何理解LSTM网络中的神经元 By 机器之心2017年7月03日 14:29 对人类而言,转写是一件相对容易并且可解释的任务,所以它比较适合用来解释神经网络做了哪些事情,以及神经网络 ...

  7. 要选择做有价值的事情

    创业应该是做对大家对行业有价值的事情,而不是做重复的事情,应该就是类似于做技术 做些有新意的,不能重复造轮子. 选择需要花时间思索.思考,是一件有挑战,并且能够提升自己的事情. 我们应该不断的提高对自 ...

  8. 双十一大促技术只做两件事情?来看看阿里巴巴的技术之道

    作为国内互联网技术的典型代表,阿里巴巴的技术一直备受关注 编者按:本文来自微信公众号"InfoQ"(ID:infoqchina),36氪经授权发布. 支付宝的高可用与容灾架构演进 ...

  9. 坚持做一件事情真的很不容易,首先必须要克服惰性!

    坚持做一件事情真的很不容易,首先必须要克服惰性! 上面是我这个刚出社会的职场小白,最有体会的一句话! 想要真的提高自己的专业水平,除了工作之外,还要不断总结,不断学新的知识. 上面是技术大牛的知识结构 ...

最新文章

  1. 首次 统一调度系统规模化落地,全面支撑阿里巴巴双 11 全业务
  2. Docker精华问答 | task与executor有什么关系?
  3. Glide加载相同地址图片,不缓存
  4. 博文视点大讲堂第33期——如何让你既能干得漂亮又说得清楚?
  5. 记录mt7615e wifi 驱动移植到openwrt cc
  6. oracle重建orainventory,重建oraInventory解决ORA-20001
  7. 网络层—简单的arp断网
  8. 超级好用的在线绘图工具
  9. 外卖cps分销公众号小程序淘客项目,引发的思考(附0基础搭建源码)
  10. 荣耀手表magic2是否支持鸿蒙,荣耀Magic Watch 2支持哪些运动模式
  11. 【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
  12. 乐里斗未能链接服务器,LOONEY TUNES 反斗世界无法连接服务器是什么原因
  13. php中遍历一个数组,php中遍历数组的方法
  14. 利用 队列 来实现医院挂号模拟看病系统(c++,顺序及链式)
  15. 一直以为做报表只能用EXCEL和PPT,直到我看到了这套模板(附模板)
  16. 老师傅提问,电脑上网后是怎么知道自己IP的?
  17. 移动营销实务十讲导读(图文版)
  18. [Python图像处理] 使用高通滤波器实现同态滤波
  19. 有哪些400以内的蓝牙耳机值得推荐?400元以下蓝牙耳机推荐!
  20. os.listdir的随机性

热门文章

  1. linux网络编程之IP协议首部格式与其配套使用的四个协议(ARP,RARP,ICMP,IGMP)和TCP、UDP协议头结构总结
  2. Android之编程中存在性能影响的主要方面
  3. (附)python3 只需3小时带你轻松入门——python常用一般性术语或词语的简单解释
  4. 织梦php远程连接数据库,用PHP连接Oracle for NT 远程数据库
  5. 年度迷惑新闻:美女其实是个男生?
  6. 三年磨一剑,五次被拒稿,交大博士坚持稿件申诉,终发表学科顶刊
  7. 马斯克又要搞事情,不锈钢材质的Space X“星际飞船”正式亮相
  8. pythonresponse对象的属性_Scrapy中response属性以及内容提取
  9. java sql objects_Java SQL注入学习笔记
  10. docker 修改阿里镜像源_Jetson Nano 修改源镜像