Spring Boot 启动过程详细分析
Spring Boot 的启动过程是面试中常见的重点问题,其背后涉及多个核心组件的协作。本文将深入剖析 Spring Boot 的启动细节,逐一说明每个步骤由哪个组件调用了什么功能,并提供请求链路图以直观展示整个流程。
启动入口:SpringApplication.run()
Spring Boot 应用的启动从 SpringApplication.run() 开始。这是开发者最熟悉的代码入口。
- 组件:
org.springframework.boot.SpringApplication - 功能:
run(String... args)方法是静态方法,接收命令行参数并启动应用。 - 细节:
- 创建
SpringApplication实例。 - 调用实例方法
run(args)执行启动逻辑。
- 创建
代码示例:
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
第一步:SpringApplication 实例化
- 组件:
org.springframework.boot.SpringApplication - 功能:构造函数
SpringApplication(ResourceLoader, Class<?>...) - 细节:
- 设置资源加载器:
this.resourceLoader = resourceLoader,通常为null,后续会根据环境动态加载。 - 设置主配置类:
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)),传入MyApplication.class。 - 推断应用类型:
this.webApplicationType = WebApplicationType.deduceFromClasspath(),通过类路径检测是否包含 Servlet 或 Reactive 相关类,决定是SERVLET、REACTIVE还是NONE。 - 初始化监听器和初始化器:
setInitializers()调用getSpringFactoriesLoader().loadFactoryNames(ApplicationContextInitializer.class)从META-INF/spring.factories加载初始化器。setListeners()加载ApplicationListener。
- 设置资源加载器:
面试考点:如何自定义 ApplicationContextInitializer 或 ApplicationListener?答案是实现对应接口并在 spring.factories 中注册。
第二步:run 方法执行
SpringApplication.run() 是启动的核心逻辑,包含多个子步骤。
2.1 配置环境准备
- 组件:
org.springframework.boot.SpringApplication - 功能:
prepareEnvironment(listeners, applicationArguments) - 细节:
- 创建环境:
ConfigurableEnvironment environment = getOrCreateEnvironment(),根据webApplicationType创建StandardEnvironment(非 Web)或StandardServletEnvironment(Web)。 - 加载配置:
configureEnvironment(environment, args),绑定命令行参数到环境变量。 - 触发事件:
listeners.environmentPrepared(environment),通过SpringApplicationRunListeners广播ApplicationEnvironmentPreparedEvent。
- 创建环境:
面试考点:环境变量如何加载?PropertySource 的加载顺序是什么?(答案:命令行参数 > 系统属性 > 配置文件)
2.2 创建 ApplicationContext
- 组件:
org.springframework.boot.SpringApplication - 功能:
createApplicationContext() - 细节:
- 根据
webApplicationType:SERVLET:创建AnnotationConfigServletWebServerApplicationContext。REACTIVE:创建AnnotationConfigReactiveWebServerApplicationContext。NONE:创建AnnotationConfigApplicationContext。
- 使用
ApplicationContextFactory创建上下文。
- 根据
面试考点:ApplicationContext 和 BeanFactory 的区别?Spring Boot 如何选择上下文类型?
2.3 准备 ApplicationContext
- 组件:
org.springframework.boot.SpringApplication - 功能:
prepareContext(context, environment, listeners, applicationArguments, banner) - 细节:
- 绑定环境:
context.setEnvironment(environment)。 - 注册配置类:
context.getBeanDefinitionRegistry().registerBeanDefinition()注册主配置类。 - 加载 Bean 定义:
load(context, sources),通过BeanDefinitionLoader解析注解配置。 - 触发事件:
listeners.contextPrepared(context)。
- 绑定环境:
2.4 刷新 ApplicationContext
- 组件:
org.springframework.context.ConfigurableApplicationContext - 功能:
refresh() - 细节:
- BeanFactory 准备:
prepareBeanFactory()配置类加载器、添加后处理器(如ConfigurationClassPostProcessor)。 - 后处理器执行:
invokeBeanFactoryPostProcessors()处理@Configuration和@Bean。 - 注册 BeanPostProcessor:
registerBeanPostProcessors()。 - 初始化消息源:
initMessageSource()。 - 初始化事件发布者:
initApplicationEventMulticaster()。 - 启动嵌入式 Web 服务器:
- 组件:
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext - 功能:
createWebServer(),默认使用 Tomcat(TomcatServletWebServerFactory)。
- 组件:
- Bean 创建:
finishBeanFactoryInitialization()实例化所有单例 Bean。
- BeanFactory 准备:
面试考点:refresh() 的 12 个步骤是什么?嵌入式 Tomcat 是如何启动的?
2.5 启动后处理
- 组件:
org.springframework.boot.SpringApplication - 功能:
afterRefresh(context, args) - 细节:
- 触发
ApplicationStartedEvent和ApplicationReadyEvent。
- 触发
请求链路图
以下是 Spring Boot 启动的请求链路图,使用 Mermaid 语法绘制:
sequenceDiagram
participant M as Main
participant SA as SpringApplication
participant ENV as Environment
participant CTX as ApplicationContext
participant WS as WebServer
M->>SA: run(MyApplication.class, args)
SA->>SA: new SpringApplication()
SA->>ENV: getOrCreateEnvironment()
SA->>ENV: configureEnvironment(args)
SA->>CTX: createApplicationContext()
SA->>CTX: prepareContext()
CTX->>CTX: refresh()
CTX->>WS: createWebServer()
WS-->>CTX: Web Server Started
CTX-->>SA: ApplicationReadyEvent
SA-->>M: Application Running
总结
Spring Boot 的启动过程可以总结为以下关键步骤:
- 实例化 SpringApplication:加载初始化器和监听器。
- 环境准备:配置
Environment。 - 上下文创建与刷新:初始化
ApplicationContext并加载 Bean。 - Web 服务器启动:嵌入式容器(如 Tomcat)启动。
- 事件广播:通知应用就绪。