Spring Boot一站式运行流程,一探究竟!

前言

如果非说Spring Boot微框架提供了点儿自己特有的东西,,在核心类层面,也就是SpringApplication了。它提供了Spring Boot程序启动的一站式解决方案。在没有特殊需求的情况下,默认模板化后的执行流程就可以满足需求了;但有特殊需求也没关系,SpringApplication在合适的流程结点开放了一系列不同类型的扩展点,我们可以通过这些扩展点对SpringBoot程序的启动和关闭过程进行扩展。

正文

上一篇文章《Spring Boot核心运行原理神秘的面纱!》通过分析SpringApplication类实例化的代码我们知道在此过程中完成了基本的配置文件的加载和实例化。当SpringApplication对象创建之后,通过调用run方法来进行Spring Boot的启动和运行。

run方法核心流程

我们通过约定run方法的源代码对该方法的主要流程大体可以归纳如下:

  • 获取监听器和参数配置
  • 打印Banner
  • 创建并初始化容器
  • 监听器发送通知

      /**
       * 运行Spring应用,创建并刷新一个新的IOC容器并返回
       */
      public ConfigurableApplicationContext run(String... args) {
          //创建一个用于统计run方法启动时长的对象
          StopWatch stopWatch = new StopWatch();
          //启动
          stopWatch.start();
          //声明应用上下文
          ConfigurableApplicationContext context = null;
          //创建异常集合
          Collection exceptionReporters = new ArrayList<>();
          configureHeadlessProperty();
          SpringApplicationRunListeners listeners = getRunListeners(args);
          //启动监听
          listeners.starting();
          try {
              //创建应用程序启动参数
              ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
              //加载所有的配置属性
              ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
              configureIgnoreBeanInfo(environment);
              //打印Banner
              Banner printedBanner = printBanner(environment);
              //创建容器
              context = createApplicationContext();
              //获取异常信息
              exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                      new Class[] { ConfigurableApplicationContext.class }, context);
              //准备容器
              prepareContext(context, environment, listeners, applicationArguments, printedBanner);
              //初始化容器
              refreshContext(context);
              //初始化后操作
              afterRefresh(context, applicationArguments);
              //停止时长统计
              stopWatch.stop();
              //打印启动日志
              if (this.logStartupInfo) {
                  new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
              }
              //通知监听器,容器启动完成
              listeners.started(context);
              //调用ApplicationRunner和CommandLineRunner方法
              callRunners(context, applicationArguments);
          }
          catch (Throwable ex) {
                //异常处理
              handleRunFailure(context, ex, exceptionReporters, listeners);
              throw new IllegalStateException(ex);
          }
    
          try {
              //通知监听器,容器正在运行
              listeners.running(context);
          }
          catch (Throwable ex) {
              //异常处理
              handleRunFailure(context, ex, exceptionReporters, null);
              throw new IllegalStateException(ex);
          }
          return context;
    

当然,除了核心操作,run方法运行过程中还涉及到了启动时长统计、异常、日志等辅助操作。

深入探索执行流程

Spirng Boot启动过程重点在于事件监听、初始化环境、容器创建及初始化操作。大体归纳如下:

  1. 收集并加载各种可用的条件和回调接口,例如:ApplicationContextInitializer和的ApplicationListener等。调用它们的started()方法,通知它们:“Spring Boot应用要开始执行了”。
  2. 创建并准备所有的Environment(配置属性),遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,通知它们:“当前SpringBoot应用使用的Environment准备好了”。
  3. 创建并初始化ApplicationContext,例如:设置Environment,加载配置等。遍历调用所有SpringApplicationRunListener的contextPrepared()方法,通知它们:“SpringBoot应用使用的ApplicationContext准备好了”。)遍历调用所有SpringApplicationRunListener的contextLoaded()方法,告知所有SpringApplicationRunListener, ApplicationContext"装填完毕"。
  4. 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。注册并执行CommandLineRunner。)正常情况下,遍历执行SpringApplicationRunListener的finished()方法,告知它们:“OK!”。

至此,一个完整的SpringBoot应用启动完毕!

总结

至此,我们对SpringBoot的核心组件完成了基本的剖析,综合来看,大部分的东西都是Spring框架背后原有的一些概念和实践方式,SpringBoot只是在这些概念和实践方式上对特定的场景实现进行了固化和升华,而也恰恰是这些固化让我们开发基于Spring框架的应用更加方便高效。

最后的最后

为初学者提供学习指南,为从业者提供参考价值。我坚信码农也具有产生洞见的能力。扫描下图二维码关注,学习和交流!

你可能感兴趣的:(Spring Boot一站式运行流程,一探究竟!)