【框架----SpringBoot】【1.0】【附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之配置文件
  • 事件发布器发布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揭秘-快速构建微服务体系》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值