Springboot启动流程

Springboot启动流程

本文使用的SpringBoot版本为:2.7.4

Springboot启动流程(概括)

1、首先创建SpringApplication实例,在构造方法里(初始化属性):
(1)判断Web应用类型是响应式REACTIVE的,还是基于SERVLET的web应用 WebApplicationType
(2)读取spring.factories加载初始化器 ApplicationContextInitializer
(3)读取spring.factories加载监听器 ApplicationListener

2、实例化之后,执行run方法主体:run方法执行流程是基于观察者模式的,整个Springboot的启动流程实际就是各种事件的发布。
(1)获取并启用监听器 ApplicationListener,并发布应用启动事件 SpringApplicationRunListener
(2)准备环境变量,包括系统属性、启动参数以及用户配置的属性 prepareEnvironment方法
(3)创建应用程序上下文 createApplicationContext方法
(5)准备上下文环境 prepareContext方法,执行实现ApplicationContextInitializer接口的类
(6)刷新上下文 refreshContext方法,自动装配和启动tomcat
(7)发布应用启动成功事件

以上是对Springboot应用启动流程的概括总结,下面让我们结合源码具体深入的了解下Springboot的启动流程。

Springboot启动流程(详细)

入口启动类中最主要的就是@SpringBootApplication注解和SpringApplication.run方法。

@SpringBootApplication
public class SpringbootMybatisApplication {

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

}

@SpringBootApplication注解主要包含以下三个注解:

@Configuration 配置类

@EnableAutoConfiguration 自动装配,将所有符合条件的bean定义加载到IOC容器

@ComponentScan 自动扫描并加载符合条件的组件或bean

1、SpringApplication准备阶段

SpringApplication构造方法代码如下:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = new ArrayList<>(
            getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

准备阶段,首先创建SpringApplication实例,在构造方法里初始化一些属性:

(1)判断Web应用类型:(WebApplicationType)
三种类型:
NONE 不会嵌入Web容器启动
SERVLET 基于Web容器启动
REACTIVE 响应式启动(spring5新特性)

(2)读取spring.factories加载初始化器
在setInitializers方法中,读取spring.factories配置ApplicationContextInitializer接口的实现类到集合中。

(3)读取spring.factories加载监听器
在setListeners方法中,读取spring.factories配置ApplicationListener接口的实现类到集合中。

(4)获取应用启动主类 mainApplicationClass

2、SpringApplication运行阶段

SpringApplication.run方法内容如下:

/**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        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);
        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;
}

运行阶段,执行run方法主体;run方法执行流程是基于观察者模式的,整个Springboot的启动流程实际就是各种事件的发布。

(1)获取并启用监听器 ApplicationListener,并发布应用启动事件 SpringApplicationRunListener

EventPublishingRunListener监听方法与 Spring Boot 事件对应关系

监听方法SpringBoot事件起始版本
starting()ApplicationStartingEvent1.5
enviromentPrepared(ConfigurableEnvironment)ApplicationEnvironmentPreparedEvent1.0
contextPrepared(ConfigurableApplicationContext)
contextLoaded(ConfigurableApplicationContext)ApplicationPreparedEvent1.0
started(ConfigurableApplicationContext)ApplicationStartedEvent2.0
running(ConfigurableApplicationContext)ApplicationReadyEvent2.0
failed(ConfigurableApplicationContext,Throwable)ApplicationFailedEvent1.0

(2)准备环境变量,包括系统属性、启动参数以及用户配置的属性 prepareEnvironment方法

根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableEnvironment 实例:

Web Reactive: StandardEnvironment
Web Servlet: StandardServletEnvironment
非 Web: StandardEnvironment

(3)创建应用程序上下文 createApplicationContext方法
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableApplicationContext 实例:

Web Reactive: AnnotationConfigReactiveWebServerApplicationContext
Web Servlet: AnnotationConfigServletWebServerApplicationContext
非 Web: AnnotationConfigApplicationContext

(5)准备上下文环境 prepareContext方法,执行实现ApplicationContextInitializer接口的类
(6)刷新上下文 refreshContext方法,自动装配和启动tomcat
(7)刷新上下文后置处理 afterRefresh方法,空方法,供子类重写
(8)发布应用启动成功事件 listeners.started方法
(9)执行自定义的run方法。ApplicationRunner和CommandLineRunner

(完)

最后修改于:2022年10月05日 14:48

添加新评论