Spring Boot

Spring Boot启动流程

@SpringBootApplication注解

Spring Boot的启动,首先需要一个加了@SpringBootApplication注解的启动类

@SpringBootApplication 注解

这个注解本质上,是由@EnableAutoConfiguration@SpringBootConfiguration@ComponentScan三个注解连起来构成。

  • @EnableAutoConfiguration最为核心

    会导入自动配置AutoConfigurationImportSelector类,这个类会将所有符合条件的@Configuration配置都进行加载。

    @EnableAutoConfiguration 注解
  • @SpringBootConfiguration等同于@Configuration

    将当前类标记为配置类,加载到容器中。

    @SpringBootConfiguration 注解

  • @ComponentScan自动扫描并加载符合条件的Bean


SpringApplication.run方法

image-20231028185647082

在run方法开始执行后,会经历如下4个阶段

  1. 服务构建

    构建SpringApplication本身。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    // 1. 将资源加载器、主方法类加载至内存中
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

    // 2. 逐一判断对应的服务类是否存在,来确定Web服务的类型。默认是基于Servlet的Web服务,如Tomcat
    this.webApplicationType = WebApplicationType.deduceFromClasspath();

    // 3. 加载初始化类,读取所有"META-INF/spring.factories"文件中的
    // 注册初始化、上下文初始化、监听器这三类配置
    // Spring Boot和Spring Boot Autoconfigure这两个工程中配置了7个上下文初始化和8个监听器
    this.bootstrapRegistryInitializers = new ArrayList<>(
    getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); // 没有默认的注册初始化配置
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

    // 通过StackWalker判断出main方法所在的类(大概率就是启动类本身)
    this.mainApplicationClass = deduceMainApplicationClass();
    }
  2. 环境准备

    SpringApplication.run就是进入环境准备阶段。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    public ConfigurableApplicationContext run(String... args) {
    // ...

    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);
    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) {
    if (ex instanceof AbandonedRunException) {
    throw ex;
    }
    handleRunFailure(context, ex, listeners);
    throw new IllegalStateException(ex);
    }
    try {
    if (context.isRunning()) {
    Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
    listeners.ready(context, timeTakenToReady);
    }
    }
    catch (Throwable ex) {
    if (ex instanceof AbandonedRunException) {
    throw ex;
    }
    handleRunFailure(context, ex, null);
    throw new IllegalStateException(ex);
    }
    return context;
    }
  3. 容器创建

  4. 填充容器