初窥Spring源码之Boot(二)

85 阅读2分钟

前言

作为Java程序员,我们必不可少的技术就是Spring了,对于Spring来说,SpringBoot也是把他推到一代神的一个框架,与其说他是一个框架,其实可以说他是一个脚手架,今天我们来学习一下SpringBoot的启动流程,以及核心方法run

SpringBoot的启动流程

  • 入口类Application中main方法作为程序的主入口
  • 调用SpringApplication的静态方法run方法
  • 创建一个SpringApplication的实例对象,调用实例对象的run方法
  • 查询并加载SpringApplication监听器,并通知这些监听器将要执行
  • 创建并准备SpringBoot需要使用的环境
  • 进行ApplicationContext的初始化
  • 通过@EnableAutoConfigruation注解,将所需要配置加载到IOC容器中,也就是ApplicationContext
  • 进行ApplicationContext的刷新操作,让IOC容器变成可用状态
  • 再次进行ApplicationContext的刷新操作,这一步主要是为了检查是否有扩展功能
  • 启动完毕

image.png

run方法

SpringBoot版本:2.7.2

//SpringBoot最终调用的run方法
public ConfigurableApplicationContext run(String... args) {
   //计时器用于计时
   long startTime = System.nanoTime();
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
   //设置java.awt.headless 属性是true还是false ,默认为true
   configureHeadlessProperty();
   //获取所有在构造器中读取加载的监听器
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //启动监听器
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
      //将args参数封装为ApplicationArguments对象
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      //生成一个环境变量,也就是准备环境
      ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      //进行环境的初始化,也就是创建环境
      configureIgnoreBeanInfo(environment);
      //打印Banner
      Banner printedBanner = printBanner(environment);
      //ApplicationContext的初始化
      context = createApplicationContext();
      context.setApplicationStartup(this.applicationStartup);
      //刷新ApplicationContext前的准备工作
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
      //ApplicaitonContext的刷新,将IOC变为可用状态
      refreshContext(context);
      //第二次刷新,目的是为了扩展功能
      afterRefresh(context, applicationArguments);
      //计算启动时间
      Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
      //启动日志的输出
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
      }
      //发布启动完成事件
      listeners.started(context, timeTakenToStartup);
      //执行所有的runner
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, listeners);
      throw new IllegalStateException(ex);
   }
   try {
      Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
      listeners.ready(context, timeTakenToReady);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, null);
      throw new IllegalStateException(ex);
   }
   return context;
}