Spring Boot 启动加载执行链路分析

0 阅读6分钟

看源码太枯燥,我们学思维就好;细节不深究,框架只要搭起来,剩下的就是按部就班的填空了。

一、核心启动流程概览

在这里插入图片描述


二、详细执行链路分析

1. 入口:main() 方法

码友们肯定都知道,SpringBoot的启动,只需要依赖web,然后再写以一个如下的main启动方法,就可以搭建起一个web服务了。

聪明的码友如果想知道:在main运行的那一刻,SpringBoot框架到底做了哪些事情?可以看看SpringBoot 启动入口深度解析:main方法执行全流程

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args); // 启动入口
    }
}

主类上需要添加@SpringBootApplication,不加就会报错

2. 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));// 加载Listener
    this.mainApplicationClass = deduceMainApplicationClass();
}

关键步骤:

  • 推断应用类型:检查类路径(Servlet/Reactive/None)
  • 加载spring.factories:从META-INF/spring.factories加载扩展点
  • 初始化引导注册器:Spring Boot 3.0+ 新增BootstrapRegistry机制

3. 环境准备(Environment

// SpringApplication.run() → prepareEnvironment()
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // 1. 创建环境实例
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 2. 配置环境(命令行参数、Profile 等)
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 3. 附加配置属性源(支持 Spring Boot 配置绑定)
    ConfigurationPropertySources.attach(environment);
    // 4. 发布 "环境准备完成" 事件(允许监听器修改环境)
    listeners.environmentPrepared(bootstrapContext, environment);
    // 5. 调整默认属性源位置(确保优先级正确)
    DefaultPropertiesPropertySource.moveToEnd(environment);
    // 6. 校验环境前缀属性(防止非法配置)
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
        "Environment prefix cannot be set via properties.");
    // 7. 将环境属性绑定到 SpringApplication 对象
    bindToSpringApplication(environment);
    // 8. 环境类型转换(非自定义环境时)
    if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    // 9. 重新附加配置属性源(确保转换后属性源正确)
    ConfigurationPropertySources.attach(environment);
    return environment;
}

执行顺序:

  1. 根据应用类型(Servlet/Reactive/None)创建对应的环境对象;如StandardServletEnvironment(Web应用)
  2. 加载配置源(application.properties/application.yml)(--spring.profiles.active 参数
  3. 发布ApplicationEnvironmentPreparedEvent
    • 触发ConfigFileApplicationListener加载配置文件
    • 触发LoggingApplicationListener初始化日志系统

4. 创建应用上下文(ApplicationContext

// SpringApplication.run() → createApplicationContext()
protected ConfigurableApplicationContext createApplicationContext() {
    return this.applicationContextFactory.create(this.webApplicationType);
}
// 默认创建 AnnotationConfigServletWebServerApplicationContext(Web应用)

创建的应用上下文类型:

应用类型上下文实现类说明
SERVLETAnnotationConfigServletWebServerApplicationContext支持 Servlet Web 应用(Tomcat/Jetty),整合了 Web 服务器启动
REACTIVEAnnotationConfigReactiveWebServerApplicationContext支持响应式 Web 应用(Netty/WebFlux),内置响应式服务器启动
NONEAnnotationConfigApplicationContext标准非 Web 应用上下文,仅处理 Spring Bean 容器
  1. applicationContextFactory 的来源
    • 默认使用 ApplicationContextFactory.DEFAULT 实现
    • 可通过 SpringApplication.setApplicationContextFactory() 自定义
  2. webApplicationType的确定
    SpringApplication 构造阶段通过以下方式确定:
this.webApplicationType = WebApplicationType.deduceFromClasspath();

根据类路径推断应用类型:

  • 存在 DispatcherHandlerREACTIVE

  • 存在 ServletConfigurableWebApplicationContextSERVLET

  • 其他 → NONE (普通 Java 应用)

  1. 工厂创建逻辑 (ApplicationContextFactory.create())

5. 准备上下文(prepareContext()

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
    // 1. 设置环境到上下文
    context.setEnvironment(environment);
    
    // 2. 后处理应用上下文
    postProcessApplicationContext(context);
    
    // 3. 处理AOT生成的初始化器
    addAotGeneratedInitializerIfNecessary(this.initializers);
    
    // 4. 应用初始化器
    applyInitializers(context);
    
    // 5. 发布ContextPrepared事件
    listeners.contextPrepared(context);
    
    // 6. 关闭引导上下文并注册
    bootstrapContext.close(context);
    
    // 7. 记录启动信息
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    
    // 8. 注册关键单例Bean
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    
    // 9. 配置BeanFactory策略
    if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
        // 设置循环引用策略
        autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
        if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
            // 设置Bean定义覆盖策略
            listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
    }
    
    // 10. 处理延迟初始化
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    
    // 11. 添加属性源排序处理器
    context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
    
    // 12. 加载主配置源
    if (!AotDetector.useGeneratedArtifacts()) {
        Set<Object> sources = getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        load(context, sources.toArray(new Object[0]));
    }
    
    // 13. 发布ContextLoaded事件
    listeners.contextLoaded(context);
}

核心步骤:

  1. 上下文基础配置
    • 设置环境对象(context.setEnvironment(environment)
    • 执行上下文后处理(postProcessApplicationContext),如添加资源加载器
    • 应用所有初始化器(applyInitializers),执行自定义初始化逻辑
  2. 事件通知与引导关闭
    • 发布 ContextPreparedEvent 事件(listeners.contextPrepared
    • 关闭引导上下文(bootstrapContext.close),将引导阶段单例Bean迁移至主上下文
  3. 关键Bean注册
    • 注册启动参数Bean(springApplicationArguments
    • 注册Banner打印对象(springBootBanner
    • 配置BeanFactory策略(循环引用/Bean覆盖等)
  4. 特殊处理
    • 添加懒加载处理器(若启用全局懒加载)
    • 添加属性源排序处理器(确保配置优先级)
    • 加载主配置源(getAllSources() + load()
  5. 最终事件通知
    • 发布 ContextLoadedEvent 事件(listeners.contextLoaded),允许最终调整上下文

6. 刷新上下文(refreshContext() → 核心!)

// AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 阶段0: 刷新准备
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        this.prepareRefresh(); // 准备刷新上下文

        // 阶段1: 获取新BeanFactory
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

        // 阶段2: 配置BeanFactory
        this.prepareBeanFactory(beanFactory);

        try {
            // 阶段3: 后处理BeanFactory
            this.postProcessBeanFactory(beanFactory);

            // 阶段4: 执行BeanFactory后处理器
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            this.invokeBeanFactoryPostProcessors(beanFactory); // 关键:加载配置类/配置属性
            this.registerBeanPostProcessors(beanFactory);      // 注册Bean后处理器
            beanPostProcess.end();

            // 阶段5: 初始化消息源
            this.initMessageSource();

            // 阶段6: 初始化事件广播器
            this.initApplicationEventMulticaster();

            // 阶段7: 扩展点:子类初始化特殊Bean
            this.onRefresh(); // Spring Boot 在此启动Web服务器

            // 阶段8: 注册监听器
            this.registerListeners();

            // 阶段9: 完成BeanFactory初始化
            this.finishBeanFactoryInitialization(beanFactory); // 实例化所有非懒加载单例

            // 阶段10: 完成刷新
            this.finishRefresh(); // 发布ContextRefreshedEvent事件

        } catch (BeansException ex) {
            // 异常处理:销毁已创建Bean并取消刷新
            this.destroyBeans();
            this.cancelRefresh(ex);
            throw ex;
        } finally {
            // 清理缓存
            this.resetCommonCaches();
            contextRefresh.end();
        }
    }
}

关键扩展点详解:

1. invokeBeanFactoryPostProcessors() - 自动配置入口

this.invokeBeanFactoryPostProcessors(beanFactory);

扩展机制

  • 执行 ConfigurationClassPostProcessor处理 @Configuration
  • Spring Boot 关键:触发 AutoConfigurationImportSelector
    • 扫描 META-INF/spring.factories 加载自动配置类
    • 执行条件注解过滤 (@ConditionalOnClass等)
    • 加载顺序控制:@AutoConfigureOrder, @AutoConfigureBefore/After

典型流程

在这里插入图片描述

2. onRefresh() - 内嵌服务器启动

protected void onRefresh() {
    super.onRefresh();
    createWebServer(); // Spring Boot 扩展
}

扩展实现:

  • ServletWebServerApplicationContext 中:
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer(); // 创建并启动Tomcat/Jetty/Undertow
    } catch (Throwable ex) {...}
}

核心动作

  1. BeanFactory获取ServletWebServerFactory
  2. 使用 factory.getWebServer() 创建服务器实例
  3. 绑定 server.port 等配置属性
  4. 注册DispatcherServlet (Servlet 环境) 或 WebHandler (响应式环境)

3. finishBeanFactoryInitialization()- 单例初始化扩展

finishBeanFactoryInitialization(beanFactory);

Spring Boot 扩展点:

  • 健康检查系统:HealthEndpointAutoConfiguration
    • **注册 **HealthContributorRegistry
    • 内置磁盘/数据源/JMS 等健康指示器
  • 配置属性绑定ConfigurationPropertiesBindingPostProcessor
    • **处理 **@ConfigurationProperties 注解
    • 将环境属性绑定到 Bean 字段
  • 启动指标:ApplicationStartup 实现
    • 记录 Bean 初始化耗时
    • **跟踪 **@Bean 方法执行

4. finishRefresh() - 生命周期回调

protected void finishRefresh() {
    // 1. 发布ContextRefreshedEvent
    publishEvent(new ContextRefreshedEvent(this));
    
    // 2. Spring Boot扩展:启动完成处理
    LiveBeansView.registerApplicationContext(this);
}

7. 刷新后处理

// 扩展点
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);

执行顺序:

  1. 发布ApplicationStartedEvent
  2. 执行ApplicationRunnerCommandLineRunner
    • @Order顺序执行
  3. 发布ApplicationReadyEvent

三、Spring框架集成关键点

  1. 自动配置原理
    • 条件注解:@ConditionalOnClass@ConditionalOnMissingBean
    • 配置类:spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  2. Servlet容器启动
    • ServletWebServerFactoryAutoConfiguration → 创建TomcatServletWebServerFactory
    • DispatcherServletAutoConfiguration → 注册DispatcherServlet
  3. 数据源与事务
    • DataSourceAutoConfiguration → 创建DataSource
    • TransactionAutoConfiguration → 启用@Transactional

四、思维导图总结

版本说明

  • Spring Boot 3.5.0 使用 Spring 6.2.7
  • 自动配置路径:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  • 事件驱动模型:ApplicationEvent + ApplicationListener