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. Android中 Application的使用

    Application全局唯一,如果需要放置全局的变量,需要用到Application,类似于OC中的单例类,获者OC中的AppDelegate 第一步:创建一个AppContext继承Applica ...

  2. [js]ext.js探索

    Ext JS 经常会遇到布局等头疼的问题,一直在用bootstrap,但是我不喜欢这玩意出的效果想找个合适的js架构入手 http://examples.sencha.com/extjs/6.6.0/ ...

  3. 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 ...

  4. etcd 集群部署

    etcd web管理 https://nikfoundas.github.io/etcd-viewer/ # git clone https://github.com/nikfoundas/etcd- ...

  5. EM算法小结

    一.什么是EM算法? EM算法是机器学习中一个很重要的算法,即期望最大化算法,主要包括以下两个步骤: E步骤:estimate the expected values M步骤:re-estimate ...

  6. Log Parser 2.2 + Log Parser Lizard GUI 分析IIS日志示例

    Log Parser 日志分析工具,用命令行操作,可以分析 IIS logs,event logs,active directory,log4net,file system,t-sql Log Par ...

  7. 计算auc-python/awk

    1.自己写的计算auc的代码,用scikit-learn的auc计算函数sklearn.metrics.auc(x, y, reorder=False)做了一些测试,结果是一样的,如有错误,欢迎指正. ...

  8. MVC备忘笔记

    1.增加样式 @Html.EditorFor(model => model.AssociationName, new { @class="inputtext input-220&quo ...

  9. Dapper Extensions中修改Dialect

    如果是MySql数据库,则修改为:DapperExtensions.DapperExtensions.SqlDialect = new MySqlDialect(); DapperExtensions ...

  10. FastReport问题整理(转)

    FastReport问题整理 博客分类: 软件开发   部分来自网上,部分来自网友,部分来自Demo如果有新的内容,会不断更新.. 更新历史: 2009-02-27 加入套打方案全攻略(原:jinzh ...