SpringBoot运行流程(11大执行流程图解)

SpringBoot运行流程(11大执行流程图解)-mikechen

SpringBoot运行流程,首先从 Spring Application调用 run 方法开始,如下所示:

@SpringBootApplication 
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

在main主方法中:调用了SpringApplication的run方法,该方法完成了整个SpringBoot的启动流程。

下面让我们一起来看一下这个方法执行过程中都做了哪些工作:

//SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return new SpringApplication(primarySources).run(args);
}

由上面的代码可以指定,run方法在SpringApplication是一个静态方法,该方法会将传入的启动类(Application.class)作为SpringApplication的构造参数来创建一个SpringApplication的实例。

下面我们看一下run方法的代码实现:

//SpringApplication的run方法
public ConfigurableApplicationContext run(String... args) {
  //创建StopWatch对象用于统计run方法的执行耗时
   StopWatch stopWatch = new StopWatch();
  //调用start方法表示开始启动计时
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        //通过SPI机制加载所有的SpringApplicatoinRunListener监听器
    //SpringBoot启动过程的不同阶段会回调该监听器的不同方法
   SpringApplicationRunListeners listeners = getRunListeners(args);
  //调用SpringApplicatoinRunListener的starting方法
   listeners.starting();
   try {
     //将SpringApplication的启动参数封装为ApplicationArguments
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
     //创建SpringBoot应用使用的环境变量对象,内部会根据webApplicationType创建不同的环境对象,
     //这里会创建StandardServletEnvironment对象
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
     //打印banner,默认是在管控台打印SpringBoot
      Banner printedBanner = printBanner(environment);
     //创建使用的ApplicationContext上下文对象,这里会根据webApplicationType创建不同的对象上下文对象
     //这里创建的是AnnotationConfigServletWebServerApplicationContext对象
      context = createApplicationContext();
     //通过SPI机制加载SpringBoot的异常报告对象SpringBootExceptionReporter
     //当SpringBoot启动过程中抛出异常时,会通过该对象打印错误日志
      exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
  	//ApplicationContext上下文对象创建完毕后,会调用prepareContext为ApplicationContext做一些准备工作
  	//比如为ApplicationContext设置环境变量,回调ApplicationContextInitializer对象的initialize方法等
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  		//调用ApplicationContext的refresh方法,启动整个Spring应用程序
      refreshContext(context);
  		//停止StopWatch计时器
      stopWatch.stop();
  		//调用SpringApplcationListener对象的started监听方法
      listeners.started(context);
  	  //回调Spring中的的ApplicationRunner对象和CommandLineRunner对象
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
     //抛出异常,则使用SpringExceptionReporter打印异常报告
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
     //启动成功,则调用SpringApplicationListener对象的running监听方法
      listeners.running(context);
   }
   catch (Throwable ex) {
     //抛出异常,则使用SpringExceptionReporter打印异常报告
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
  //返回创建的ApplicationContext应用上下文
   return context;
}

SpringBoot运行流程,大致分为如下11大执行流程步骤:

SpringBoot运行流程(11大执行流程图解)-mikechen

 

1)创建 Spring Application 实例,调用 run 方法,同时将启动入口类作 为参数传递进去;

2)通过 Spring Factories Loader 加载 META-INF/spring.factories 文 件;

3)然后由 SpringApplicationRunListener 来发出 starting 消息;

4)创建参数,并配置当前 SpringBoot 应用需要使用的 Environment 实 例;

5)完成之后,依然由 SpringApplicationRunListener 来发出 environmentPrepared 消息;

6)创建 Spring 的应用上下文实例:ApplicationContext,初始化该实例 并设置应用环境配置实例:Environment,同时加载相关的配置项;

7)由 SpringApplicationRunListener 发出 contextPrepared 消息,告 知 SpringBoot 应用当前使用的 ApplicationContext 已准备完毕;

8)将各种 Bean 组件装载入 Spring 的 IO 容器/应用上下文: ApplicationContext 中,继续由 SpringApplicationRunListener 来发出 contextLoaded 消息,告知 SpringBoot 应用当前使用的 ApplicationContext 已准备完毕;

9)重新刷新 Refresh Spring 的应用上下文实例:ApplicationContext, 完成 IOC 容器可用的最后一步;

10)由 SpringApplicationRunListener 发出 started 消息,完成最终的 程序的启动;

11)由 SpringApplicationRunListener 发出 running 消息,告知程序已 成功运行起来了。

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法