【附4】springboot源码解析-run()
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); //设置计时器 stopWatch.start(); //记录当前时间 ConfigurableApplicationContext context = null; configureHeadlessProperty(); //设置java.awt.headless为true或false SpringApplicationRunListeners listeners = getRunListeners(args);//获取事件发布器(控制所有事件的执行时机) listeners.started(); //事件发布器发布ApplicationStartedEvent事件,所有监听了该事件的ApplicationListener实现类执行逻辑 try { context = doRun(listeners, args); stopWatch.stop(); //计时结束(记录总共花了多少时间) if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, ex); throw new IllegalStateException(ex); } }
private ConfigurableApplicationContext doRun(SpringApplicationRunListeners listeners, String... args) { ConfigurableApplicationContext context; // Create and configure the environment ConfigurableEnvironment environment = getOrCreateEnvironment(); //创建Environment configureEnvironment(environment, args); //配置Environment(包括配置要使用的PropertySource和Profile) listeners.environmentPrepared(environment); //事件发布器发布ApplicationEnvironmentPreparedEvent事件,所有监听了该事件的ApplicationListener执行相应逻辑 if (isWebEnvironment(environment) && !this.webEnvironment) { environment = convertToStandardEnvironment(environment); } if (this.bannerMode != Banner.Mode.OFF) { printBanner(environment); } // Create, load, refresh and run the ApplicationContext context = createApplicationContext(); //创建ApplicationContext容器 context.setEnvironment(environment); //设置Environment到容器 postProcessApplicationContext(context); applyInitializers(context); //执行所有的ApplicationContextInitializer的initial方法,对创建出来的ApplicationContext容器进行初始化 listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); // Load the sources Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); //将之前通过@EnableAutoConfiguration的所有配置以及其他形式的IOC容器加载到已经准备完毕的ApplicationContext listeners.contextLoaded(context); //事件发布器将所有的ApplicationListener注册给当前的ApplicationContext,之后发布ApplicationPreparedEvent事件 // Refresh the context refresh(context); //刷新ApplicationContext if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } afterRefresh(context, applicationArguments); listeners.finished(context, null); return context; }
步骤总结:
- 设置计时器,记录当前时间
- 该类是一个非线程的安全的,如果自己使用要考虑多线程的情况.
- 设置java.awt.headless为true或false
- java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true
- 获取事件发布器(用于控制所有事件的执行时机)
- 事件发布器发布ApplicationStartedEvent事件,所有监听了该事件的ApplicationListener实现类执行逻辑
- 创建并配置Environment(包括配置要使用的PropertySource和Profile)
- PropertySource主要是读取SpringApplication.setDefaultProperties指定的默认属性 + 命令行属性
- 通常,只有命令行属性,而且该属性会addFirst,说明优先级是最高的!!!
- Profile主要是读取application-{level}.properties中的内容
- 需要配置:"spring.active.profiles"
- 关于配置文件的一系列问题 见附 5 springboot之配置文件
- PropertySource主要是读取SpringApplication.setDefaultProperties指定的默认属性 + 命令行属性
- 事件发布器发布ApplicationEnvironmentPreparedEvent事件,所有监听了该事件的ApplicationListener执行相应逻辑
- 创建ApplicationContext容器
- 设置Environment到容器
- 执行所有的ApplicationContextInitializer的initial方法,对创建出来的ApplicationContext容器进行初始化
- 将之前通过@EnableAutoConfiguration的所有配置以及其他形式的IOC容器加载到已经准备完毕的ApplicationContext
- 装载beanDefinition到ApplicationContext(之后在使用Bean的时候,直接由beanDefinition初始化为bean)
- 事件发布器将所有的ApplicationListener注册给当前的ApplicationContext,之后发布ApplicationPreparedEvent事件
- 刷新ApplicationContext
- 这里如果有ContextRefreshedEvent的监听器,那么此时就会触发其onApplication方法
- 结束计时,记录整个启动时间
以上红色部分就是核心步骤!
参考:
http://www.jianshu.com/p/692b10aef052
http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow
《springboot揭秘-快速构建微服务体系》
【附4】springboot源码解析-run()的更多相关文章
- 附4 springboot源码解析-run()
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); / ...
- 附3 springboot源码解析 - 构建SpringApplication
package com.microservice.framework; import org.springframework.boot.SpringApplication; import org.sp ...
- SpringBoot源码解析系列文章汇总
相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的SpringBoot源码解析系列文章的汇总,当你使用SpringBoot不仅仅满足于基本使用时.或者出去面试被面试官虐了时.或者说想要深入了解一下 ...
- springboot源码解析-管中窥豹系列之总体结构(一)
一.简介 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之项目类型(二)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之Runner(三)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之Initializer(四)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之aware(六)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- springboot源码解析-管中窥豹系列之web服务器(七)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
随机推荐
- Android中 Application的使用
Application全局唯一,如果需要放置全局的变量,需要用到Application,类似于OC中的单例类,获者OC中的AppDelegate 第一步:创建一个AppContext继承Applica ...
- [js]ext.js探索
Ext JS 经常会遇到布局等头疼的问题,一直在用bootstrap,但是我不喜欢这玩意出的效果想找个合适的js架构入手 http://examples.sencha.com/extjs/6.6.0/ ...
- PAT 1076 Forwards on Weibo[BFS][一般]
1076 Forwards on Weibo (30)(30 分) Weibo is known as the Chinese version of Twitter. One user on Weib ...
- etcd 集群部署
etcd web管理 https://nikfoundas.github.io/etcd-viewer/ # git clone https://github.com/nikfoundas/etcd- ...
- EM算法小结
一.什么是EM算法? EM算法是机器学习中一个很重要的算法,即期望最大化算法,主要包括以下两个步骤: E步骤:estimate the expected values M步骤:re-estimate ...
- Log Parser 2.2 + Log Parser Lizard GUI 分析IIS日志示例
Log Parser 日志分析工具,用命令行操作,可以分析 IIS logs,event logs,active directory,log4net,file system,t-sql Log Par ...
- 计算auc-python/awk
1.自己写的计算auc的代码,用scikit-learn的auc计算函数sklearn.metrics.auc(x, y, reorder=False)做了一些测试,结果是一样的,如有错误,欢迎指正. ...
- MVC备忘笔记
1.增加样式 @Html.EditorFor(model => model.AssociationName, new { @class="inputtext input-220&quo ...
- Dapper Extensions中修改Dialect
如果是MySql数据库,则修改为:DapperExtensions.DapperExtensions.SqlDialect = new MySqlDialect(); DapperExtensions ...
- FastReport问题整理(转)
FastReport问题整理 博客分类: 软件开发 部分来自网上,部分来自网友,部分来自Demo如果有新的内容,会不断更新.. 更新历史: 2009-02-27 加入套打方案全攻略(原:jinzh ...