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之配置文件
  • 事件发布器发布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()的更多相关文章

  1. 【附4】springboot源码解析-run()

    public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); / ...

  2. 附3 springboot源码解析 - 构建SpringApplication

    package com.microservice.framework; import org.springframework.boot.SpringApplication; import org.sp ...

  3. SpringBoot源码解析系列文章汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的SpringBoot源码解析系列文章的汇总,当你使用SpringBoot不仅仅满足于基本使用时.或者出去面试被面试官虐了时.或者说想要深入了解一下 ...

  4. springboot源码解析-管中窥豹系列之总体结构(一)

    一.简介 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  5. springboot源码解析-管中窥豹系列之项目类型(二)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  6. springboot源码解析-管中窥豹系列之Runner(三)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  7. springboot源码解析-管中窥豹系列之Initializer(四)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  8. springboot源码解析-管中窥豹系列之aware(六)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  9. springboot源码解析-管中窥豹系列之web服务器(七)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

随机推荐

  1. Python数据分析之pandas

    Python中的pandas模块进行数据分析. 接下来pandas介绍中将学习到如下8块内容:1.数据结构简介:DataFrame和Series2.数据索引index3.利用pandas查询数据4.利 ...

  2. Request常用方法(转)

    原文地址:http://www.lihuai.net/program/python/1617.html Python Requests库:HTTP for Humans 时间: 2014/12/30 ...

  3. Java 中的异常

    前段时间集合的整理真的是给我搞得心力交瘁啊,现在可以整理一些稍微简单一点的,搭配学习 ~ 突然想到一个问题,这些东西我之前就整理过,现在再次整理有什么区别嘛?我就自问自答一下,可能我再次整理会看到不一 ...

  4. OpenGL笔记<第一章> 构建 GLSL class

    恭喜,我们终于很扎实地完成了第一章——glsl 入门 不幸的是,it's not the basic of GLSL shader ,我们下一节开篇,basic of GLSL shader 在下一章 ...

  5. java UTF8 HEX

    private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static Str ...

  6. [java] java中的初始化顺序

    先看程序: package init_cls; class A{ {System.out.println("i am in the class A!");} static { Sy ...

  7. js中对同步和异步的理解

    你应该知道,javascript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流 ...

  8. mysql_connect的$new_link参数

    假设在127.0.0.1上有test1和test2两个库, 其中库test1库中有test1表,test2中有test2表 $servername = "127.0.0.1"; $ ...

  9. [CC-SUBWAY]Subway Ride

    [CC-SUBWAY]Subway Ride 题目大意: 一棵\(n(n\le5\times10^5)\)个点的含重边的树,总边数为\(m(m\le10^6)\),每条边有一个颜色.\(q(q\le5 ...

  10. 【openjudge】 CDQZ challenge 4

    改了三天,提交17次,一定要纪念一下! 1004:Challenge 4 总时间限制:  10000ms 单个测试点时间限制:  1000ms 内存限制:  262144kB 描述 给一个长为N的数列 ...