附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 ...
随机推荐
- express增加swagger功能
参考地址:https://blog.csdn.net/freeboy1234/article/details/79289486 下载swagger ui库 地址是:https://github.com ...
- java把html标签字符转换成普通字符(反转换成html标签)
package net.jasonjiang.web; import org.junit.Test; import org.springframework.web.util.HtmlUtils; /* ...
- 使用ASP.NET MVC+Entity Framework快速搭建系统
详细资料: http://www.cnblogs.com/dingfangbo/p/5771741.html 学习 ASP.NET MVC 也有一段时间了,打算弄个小程序练练手,做为学习过程中的记录和 ...
- CSUOJ 1087 就多了两分钟
Description Yucept21和他的室友Zyn因为宿舍没电去网吧上网,上了27分钟,Cs打电话来说来电了.所以Yucept21在第29分钟下机了,上网的费用是一块钱,然后Zyn墨迹了两分钟, ...
- JAVAEE——SSH项目实战06:统计信息管理、Spring注解开发和EasyUI
作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7190925.html 一.统计信息管理 二.Spring注解开发 1.service ...
- OpenGL笔记<5> shader 调试信息获取 Debug
我们今天来讲调试信息,这个东西讲起来会比较无聊,因为都是一些函数调用,没啥可讲的,函数就是那样用的,不过其效果挺好玩的,同时在程序设计中也是很必要的,所以还是来写一下,不过,就是因为知识比较固定且简单 ...
- 用 React 编写移动应用 React Native
转载:用 React 编写移动应用 React Native ReactNative 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App.而且React ...
- python 并集union, 交集intersection, 差集difference, 对称差集symmetric_difference
python的集合set和其他语言类似,是一个无序不重复元素集, 可用于消除重复元素. 支持union(联合), intersection(交), difference(差)和sysmmetric d ...
- JMS异步消息机制
企业消息系统 Java Message Service 是由 Sun Microsystems 开发的,它为 Java 程序提供一种访问 企业消息系统 的方法.在讨论 JMS 之前,我们分来析一下企业 ...
- wpf企业应用之带选项框的TreeView
wpf里面实现层次绑定主要使用HierarchicalDataTemplate,这里主要谈一谈带checkbox的treeview,具体效果见 wpf企业级开发中的几种常见业务场景. 先来看一下我的控 ...