Spring Boot 应用程序启动时执行完整流程(最新推荐)

 更新时间:2025年11月20日 15:39:47   作者:阿萨德528号  
本文给大家介绍关于Spring Boot应用程序启动时main方法的完整执行流程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

关于Spring Boot 应用程序启动时 main 方法的完整执行流程。我会按照方法调用的核心顺序进行描述,并解释每个关键方法的作用。

核心流程总览

在Spring Boot应用中,我们通常会写一个包含main方法的类,并调用SpringApplication.run。
示例代码:

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

整个启动过程可以概括为:构造 SpringApplication 对象 -> 执行 run 方法 -> 启动内嵌服务器 -> 完成应用启动。

第一阶段:SpringApplication实例化

执行方法:new SpringApplication(primarySources)

  1. 执行 this(null, primarySources)

    • 作用:调用内部的构造器。
    • 最主要的部分是 WebApplicationType.deduceFromClasspath() 方法:
      • 这个方法的作用是:根据类路径下存在的类来推断应用类型。
      • 它会检查 DispatcherHandlerDispatcherServletServlet 等类的存在性,从而判断应用是 REACTIVE(响应式)、SERVLET(标准的 Servlet Web 应用)还是 NONE(非 Web 应用)。我们最常见的 Spring MVC 应用就是 SERVLET 类型。
  2. 执行 setInitializers 方法:

    • 作用:设置应用初始化器 (ApplicationContextInitializer)。
    • 最主要的部分是 getSpringFactoriesInstances(ApplicationContextInitializer.class) 方法:
      • 这个方法的作用是:使用 Spring 工厂加载机制,从 META-INF/spring.factories 配置文件中加载并实例化所有配置的 ApplicationContextInitializer 实现类。
      • 常见的初始化器如 ConfigurationWarningsApplicationContextInitializer(检查配置警告)、ContextIdApplicationContextInitializer(设置上下文 ID)等。这些初始化器会在 ApplicationContext 刷新之前被调用。
  3. 执行 setListeners 方法:

    • 作用:设置应用监听器 (ApplicationListener)。
    • 最主要的部分同样是 getSpringFactoriesInstances(ApplicationListener.class) 方法:
      • 这个方法的作用是:从 spring.factories 中加载并实例化所有配置的 ApplicationListener
      • 这些监听器用于监听在应用启动过程中发布的各类事件,例如 ApplicationStartedEventApplicationReadyEvent 等。ClearCachesApplicationListener(清除缓存)、FileEncodingApplicationListener(检查文件编码)都是常见的监听器。
  4. 执行 deduceMainApplicationClass 方法:

    • 作用:推导出主应用程序类(即我们写了 main 方法的那个类)。
    • 原理是:遍历当前调用栈,找到第一个方法名为 main 的类。

至此,SpringApplication 对象构造完毕,它已经准备好了初始化器和监听器。

第二阶段:执行run方法

执行方法:SpringApplication.run(primarySources, args)

这是整个启动流程最核心、最复杂的方法。

  1. 执行 getRunListeners 方法并调用 listeners.starting()

    • 作用:获取 SpringApplicationRunListeners 并发布 ApplicationStartingEvent 事件。
    • 说明:SpringApplicationRunListenersSpringApplicationRunListener 的集合,它专门用于监听 SpringApplicationrun 方法执行过程中的关键节点。第一步就是发布应用正在启动的事件。
  2. 执行 prepareEnvironment 方法:

    • 作用:准备和应用环境 (Environment),这是整个应用配置的基础。
    • 最主要的部分是:
      • getOrCreateEnvironment():根据应用类型创建 StandardEnvironmentStandardServletEnvironment
      • configureEnvironment(environment, args):配置环境,包括 PropertySources(属性源,如 JVM 系统属性、操作系统环境变量)和 Profiles(配置文件,如 “dev”, “prod”)。
      • listeners.environmentPrepared(environment):发布 ApplicationEnvironmentPreparedEvent 事件。这是一个极其重要的扩展点,监听这个事件的监听器(最著名的是 ConfigFileApplicationListener)会从 application.propertiesapplication.yml 等文件中加载我们自定义的配置属性。
  3. 执行 printBanner 方法:

    • 作用:在控制台打印 Spring Boot 的 Banner。
  4. 执行 createApplicationContext 方法:

    • 作用:创建 ApplicationContext(IoC 容器)。
    • 根据第一步推断出的 WebApplicationType,创建不同类型的上下文。对于 Servlet Web 应用,会创建 AnnotationConfigServletWebServerApplicationContext
  5. 执行 prepareContext 方法:

    • 作用:准备上面创建好的 ApplicationContext
    • 最主要的部分是:
      • postProcessApplicationContext(context):后处理应用上下文,例如设置 Bean 名称生成器、资源加载器。
      • applyInitializers(context):应用初始化器。调用在第一步中加载的所有 ApplicationContextInitializerinitialize 方法,允许我们在容器刷新前对上下文进行自定义。
      • listeners.contextPrepared(context):发布 ApplicationContextInitializedEvent 事件,通知监听器上下文已准备就绪。
      • load(context, sources.toArray(new Object[0])):将主源(即我们的 @SpringBootApplication 注解类)加载到上下文中,为后续的组件扫描和 Bean 定义注册做准备。
      • listeners.contextLoaded(context):发布 ApplicationPreparedEvent 事件,通知监听器上下文已加载完毕。

第三阶段:刷新应用上下文 (最最核心)

执行方法:refreshContext(context)

这个方法内部会调用 AbstractApplicationContext.refresh(),这是 Spring 框架容器初始化的标准流程。

  1. 执行 prepareRefresh() 方法:

    • 作用:刷新前的准备工作,例如初始化属性源、验证必要的属性。
  2. 执行 obtainFreshBeanFactory() 方法:

    • 作用:获取或刷新内部的 BeanFactoryDefaultListableBeanFactory)。BeanFactory 是 Spring 容器的基础。
  3. 执行 prepareBeanFactory(beanFactory) 方法:

    • 作用:准备 BeanFactory,配置它的类加载器、后置处理器等标准配置。
  4. 执行 postProcessBeanFactory(beanFactory) 方法:

    • 作用:允许在 Bean 定义加载完成后、实例化之前,对 BeanFactory 进行后处理。这是一个空方法,供子类扩展。
  5. 执行 invokeBeanFactoryPostProcessors(beanFactory) 方法:

    • 作用:这是 Spring Boot 自动配置的魔法入口!
    • 最主要的部分是:调用所有 BeanFactoryPostProcessor
    • 其中,ConfigurationClassPostProcessor 会解析 @Configuration 注解的类。它会发现我们的主类上的 @SpringBootApplication 注解。
    • @SpringBootApplication 中包含 @EnableAutoConfiguration,后者会导入 AutoConfigurationImportSelector
    • AutoConfigurationImportSelector 会从 META-INF/spring.factories 中加载所有 EnableAutoConfiguration 键对应的自动配置类(如 DataSourceAutoConfiguration, WebMvcAutoConfiguration)。
    • 这些自动配置类根据条件(如类路径下是否存在某个类、是否设置了某个属性等)决定是否生效,并向容器中批量添加 Bean 定义。
  6. 执行 registerBeanPostProcessors(beanFactory) 方法:

    • 作用:注册 BeanPostProcessor。这些处理器会在 Bean 实例化之后、初始化前后 被调用,用于对 Bean 进行增强(如 @Autowired, @PostConstruct 等功能都是通过 BeanPostProcessor 实现的)。
  7. 执行 initMessageSource() 方法:

    • 作用:初始化国际化相关的消息源。
  8. 执行 initApplicationEventMulticaster() 方法:

    • 作用:初始化应用事件广播器,用于事件发布。
  9. 执行 onRefresh() 方法:

    • 作用:这是 Spring Boot 创建并启动内嵌 Web 服务器的关键步骤!
    • ServletWebServerApplicationContext 中,此方法被重写。
    • 最主要的部分是 createWebServer() 方法:
      • 这个方法的作用是:从 BeanFactory 中获取 ServletWebServerFactory(如 TomcatServletWebServerFactory)。
      • 调用 factory.getWebServer(...) 方法,这会创建内嵌的 Tomcat/Jetty/Undertow 服务器实例,并初始化 Servlet 容器(初始化 DispatcherServlet 并注册到容器中)。此时,Web 服务器已经创建好,但尚未开始监听端口。
  10. 执行 registerListeners() 方法:

    • 作用:注册监听器,将事件监听器注册到第 8 步初始化的事件广播器中。
  11. 执行 finishBeanFactoryInitialization(beanFactory) 方法:

    • 作用:完成 BeanFactory 的初始化,实例化所有剩余的非懒加载单例 Bean。
    • 这是 IoC 容器依赖注入发生的主要阶段。我们的 Controller、Service、Repository 等组件都在这个阶段被创建和装配。
  12. 执行 finishRefresh() 方法:

    • 作用:完成上下文的刷新工作,发布最终事件。
    • 最主要的部分是:
      • publishEvent(new ContextRefreshedEvent(this)):发布 ContextRefreshedEvent 事件。
      • ServletWebServerApplicationContext 中,还会调用 finishRefresh() 的一个扩展,最终启动内嵌的 Web 服务器(例如 TomcatWebServer.start()),开始监听指定的端口。至此,我们的应用已经可以处理 HTTP 请求了。

第四阶段:启动后处理

  • 执行 afterRefresh(context, applicationArguments) 方法:
    • 作用:刷新后处理,默认为空。是一个扩展点。
  • 执行 listeners.started(context) 方法:
    • 作用:发布 ApplicationStartedEvent 事件,通知所有监听器应用已启动。
  • 执行 callRunners(applicationArguments) 方法:
    • 作用:调用 ApplicationRunnerCommandLineRunner 接口的实现类。
    • 这是开发者可以在应用启动后、开始接收流量前,执行一些特定初始化逻辑的常用方式。
  • 执行 listeners.ready(context, timeTaken) 方法:
    • 作用:发布 ApplicationReadyEvent 事件。这个事件标志着应用已完全启动完毕,处于就绪状态。它与 ApplicationStartedEvent 的区别在于,此时所有 Bean 都已初始化,内嵌服务器已在运行。
    • 返回 ApplicationContext
    • 作用:将已经完全初始化好的 ApplicationContext 返回。

总结

整个流程从 main 方法开始,经历了 环境准备 -> 容器创建 -> Bean定义加载(自动配置) -> Bean实例化(依赖注入) -> 内嵌服务器启动 -> 运行自定义初始化逻辑 等一系列复杂而精密的步骤,最终将一个功能完备的 Spring Boot 应用呈现在我们面前。其中 refreshContext() 是整个流程的心脏,而自动配置和内嵌服务器是 Spring Boot 两大核心特性的实现关键。

到此这篇关于Spring Boot 应用程序启动时执行流程的文章就介绍到这了,更多相关Spring Boot 启动时执行流程内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java时间格式的简单整理

    java时间格式的简单整理

    这篇文章主要介绍了java时间格式的简单整理,文中通过示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考一下
    2019-06-06
  • 详解spring项目中如何动态刷新bean

    详解spring项目中如何动态刷新bean

    这篇文章主要为大家介绍了详解spring项目中如何动态刷新bean,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • springboot 配置文件配置项前缀为0的数字特殊处理方式

    springboot 配置文件配置项前缀为0的数字特殊处理方式

    这篇文章主要介绍了springboot 配置文件配置项前缀为0的数字特殊处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 一文详解Spring Aop @After(后置通知)的使用场景

    一文详解Spring Aop @After(后置通知)的使用场景

    @After 是 Spring AOP 中的另一种通知(Advice)类型,通常被称为“后置通知”或“最终通知”,本文将通过详细的代码示例给大家介绍一下Spring Aop @After(后置通知)的使用场景,需要的朋友可以参考下
    2025-06-06
  • 教你Springboot如何实现图片上传

    教你Springboot如何实现图片上传

    这篇文章主要介绍了教你Springboot如何实现图片上传,首先大家明白图片上传,需要在数据库定义一个varchar类型的img字段图片字段,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • springboot访问静态资源遇到的坑及解决

    springboot访问静态资源遇到的坑及解决

    这篇文章主要介绍了springboot访问静态资源遇到的坑及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Maven打包jar生成javadoc文件和source文件代码实例

    Maven打包jar生成javadoc文件和source文件代码实例

    这篇文章主要介绍了Maven打包jar生成javadoc文件和source文件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • springboot整合knife4j全过程

    springboot整合knife4j全过程

    这篇文章主要介绍了springboot整合knife4j全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java中使用@CrossOrigin和Proxy解决跨域问题详解

    Java中使用@CrossOrigin和Proxy解决跨域问题详解

    这篇文章主要介绍了Java中使用@CrossOrigin和Proxy解决跨域问题详解,在Web开发中,如果前端页面和后端接口不在同一个域名下,就会发生跨域请求的问题,同源策略是浏览器的一种安全策略,它限制了来自不同源的客户端脚本在浏览器中运行时的交互,需要的朋友可以参考下
    2023-12-12
  • SpringBoot集成canal实现示例解析

    SpringBoot集成canal实现示例解析

    这篇文章主要为大家介绍了springboot整合canal的示例实现解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多多进步,早日升职加薪
    2022-02-02

最新评论