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. PHP程序员未来路在何方

    PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些技术的推 ...

  2. 洛谷——P1231 教辅的组成

    P1231 教辅的组成 题目背景 滚粗了的HansBug在收拾旧语文书,然而他发现了什么奇妙的东西. 题目描述 蒟蒻HansBug在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习 ...

  3. JAVAEE——宜立方商城02:服务中间件dubbo、工程改造为基于soa架构、商品列表实现

    1. 学习计划 第二天:商品列表功能实现 1.服务中间件dubbo 2.工程改造为基于soa架构 3.商品列表查询功能实现. 2. 将工程改造为SOA架构 2.1. 分析 由于宜立方商城是基于soa的 ...

  4. [代码审计]eml企业通讯录管理系统v5.0 存在sql注入

    0x00 前言 上周五的时候想练练手,随便找了个系统下载下来看看. 然后发现还有VIP版本,但是VIP要钱,看了一下演示站,貌似也没有什么改变,多了个导入功能?没细看. 搜了一下发现这个系统,压根就没 ...

  5. Here is a 10-line template that can solve most 'substring' problems子字符串问题的模板

    转载自leetcode评论区:https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-mo ...

  6. 复杂密码生成工具apg

    复杂密码生成工具apg   密码是身份认证的重要方式.由于密码爆破方式的存在,弱密码非常不安全.为了构建复杂密码,Kali Linux预置了一个复杂密码生成工具apg.该工具可以提供可读密码和随机字符 ...

  7. Python 实现扫码二维码登录

    最近在做一个扫码登录功能,为此我还在网上搜了一下关于微信的扫描登录的实现方式.当这个功能完成了后,我决定将整个实现思路整理出来,方便自己以后查看也方便其他有类似需求的程序猿些. 要实现扫码登录我们需要 ...

  8. [ 转载 ] Java中常用的设计模式

    Java中常用的设计模式 1.单例模式 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个 ...

  9. Qt中文本编辑器实现语法高亮功能(Qscitinlla)

    Scintilla是一个免费.跨平台.支持语法高亮的编辑控件.它完整支持源代码的编辑和调试,包括语法高亮.错误指示.代码完成(code completion)和调用提示(call tips).能包含标 ...

  10. 【BZOJ 3640】JC的小苹果 (高斯消元,概率DP)

    JC的小苹果 Submit: 432  Solved: 159 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话 ...