附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 ...
随机推荐
- 有关Virtualbox虚拟机增强功能安装的问题
在老师给定的步骤下并不能正常的完成Virtualbox虚拟机增强功能安装而是显示下图
- 用户管理和FTP服务配置
批量创建用户 python脚本:creuser.py import osulist=open('usernames','r')for x in ulist: cmd="useradd -g ...
- 把eclipse写好的web项目导入idea 部署到Tomcat
主要分为项目配置和tomcat配置两大步骤. 一.项目配置 打开idea,选择导入项 选择将要打开的项目路径后,继续选择项目的原本类型(后续引导设置会根据原本的项目类型更新成idea的项目),此例中选 ...
- [ 原创 ] git使用技巧
Git的使用--如何将本地项目上传到Github Git分支图介绍 https://www.cnblogs.com/cheneasternsun/p/5952830.html https://www. ...
- 决策树算法(ID3)
Day Outlook Temperature Humidity Wind PlayTennis 1 Sunny Hot High Weak No 2 Sunny Hot High Strong No ...
- 什么是DHTML?
DHTML是近年来网络发展进程中最振奋人心也最具实用性的创新之一.它是一种通过各种技术的综合发展而得以实现的概念(当然,不同的浏览器,实现的程度也不同),这些技术包括Javascript, VBScr ...
- luoguP3871 [TJOI2010]中位数
题目链接 luoguP3871 [TJOI2010]中位数 题解 平衡树 代码 #include<vector> #include<cstdio> #include<cs ...
- Python168的学习笔记4
关于普通文本文件的读写 python2.7中,未注明的字符都是以acsii来编码的,而要让字符能够通用,必须声明为unicode. s=u'你好',s.encode('utf8')就是指用utf8来进 ...
- ListView实现下拉刷新功能
很久没有写博客了,感觉都懒惰了,今天说一下一个自定义的空间,就是ListView下拉列表可以刷新的功能,相信很多同学都看到过这种功能,最典型的就是新浪微博的下拉刷新列表了. 废话不多说,首先呢,下拉刷 ...
- ROS知识(7)----ROS命令中的单引号`和‘的混淆问题
ROS命令中的单引号`和‘的区别,比如使用`单引号,以下的命令是正确的: $ rosrun rviz rviz -d `rospack find rbx1_nav`/sim.rviz 而使用‘单引号, ...