前置通俗铺垫 :绝大多数开发者只会编写SpringBoot主启动类、调用SpringApplication.run()启动项目,但完全不清楚底层到底做了什么。SpringBoot能够实现零配置、快速启动、自动装配、内置Web容器,全部依赖一套标准化、事件驱动的启动流程。本文基于SpringBoot官方最新文档,结合源码逐步骤拆解,从入门概念到底层源码、从启动流程到事件机制,全覆盖讲解,零基础也能彻底吃透SpringBoot启动核心原理。
一、SpringBoot启动核心整体认知
1.1 启动入口与核心作用
所有SpringBoot项目的唯一启动入口为main主方法 ,通过SpringApplication.run(启动类.class, args)实现项目启动。该方法是SpringBoot封装的一站式启动入口,统筹了环境初始化、组件加载、事件发布、IoC容器创建、Bean加载、Web容器启动、项目就绪全流程。
相较于传统SSM项目手动创建容器、加载配置、初始化组件,SpringBoot通过标准化启动流程+自动配置机制,彻底实现开箱即用、零冗余配置。
1.2 启动两大核心阶段(核心分层)
SpringBoot完整启动流程分为两大阶段,层层递进、界限清晰:
-
SpringApplication实例初始化阶段:加载全局初始化器、监听器、预判项目类型、记录启动基础信息,属于启动前置准备;
-
run方法核心启动阶段:事件发布、环境准备、上下文创建、容器刷新、Web容器启动、项目就绪,是启动核心链路。
1.3 启动事件整体认知
SpringBoot全程基于事件驱动机制 启动,每一个关键启动节点都会发布对应事件,触发对应监听器执行,是SpringBoot解耦启动逻辑、拓展功能的核心设计。本文后续会按真实启动顺序逐事件拆解。
二、第一阶段:SpringApplication初始化源码全拆解
阶段核心定位:项目执行main方法后,先创建SpringApplication实例,完成所有前置资源加载,为后续run方法启动做铺垫。
2.1 步骤1:进入构造方法初始化实例
步骤原理:通过重载构造方法,传入启动主类资源,初始化SpringApplication全局属性,基于SPI机制加载框架内置扩展组件。
核心功能:初始化资源加载器、启动主类集合、预判项目Web类型、加载初始化器与监听器、定位主启动类。
实际用途:完成项目启动前所有全局组件的预加载,保证后续启动流程可直接调用,无需重复初始化。
// SpringApplication核心构造方法(2.x 原生完整核心源码)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 1. 赋值资源加载器:用于统一读取classpath下配置、类文件、资源文件
this.resourceLoader = resourceLoader;
// 非空校验:禁止启动主类为空,拦截非法启动
Assert.notNull(primarySources, "PrimarySources must not be null");
// 存入主启动类,LinkedHashSet保证有序、去重
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 2. 自动推断当前项目Web类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 3. SPI机制加载全局上下文初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4. SPI机制加载全局事件监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 5. 自动推断项目Main启动类
this.mainApplicationClass = deduceMainApplicationClass();
}
步骤源码补充说明 :该构造方法是SpringBoot启动第一层入口,所有前置组件加载、项目类型判定均在此完成,无任何容器刷新、Bean实例化操作,仅做「启动环境预初始化」。
2.2 步骤2:预判Web应用类型
步骤原理:通过检测classpath下的核心类存在与否,自动判别项目类型,适配不同容器创建逻辑。通过类加载器判断Servlet、Reactive核心类是否存在,优先级:响应式Web > ServletWeb > 普通非Web项目。
核心源码(deduceFromClasspath 核心实现)
public static WebApplicationType deduceFromClasspath() {
// 判断是否存在响应式Web核心类(WebFlux)
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null)
&& !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)) {
return WebApplicationType.REACTIVE;
}
// 判断是否完全无Web环境
if (!ClassUtils.isPresent("javax.servlet.Servlet", null)
|| !ClassUtils.isPresent("org.springframework.web.context.ConfigurableWebApplicationContext", null)) {
return WebApplicationType.NONE;
}
// 默认Servlet Web项目(绝大多数SpringBoot项目)
return WebApplicationType.SERVLET;
}
核心功能:区分三种项目类型:Servlet Web项目、Reactive响应式项目、非Web普通Java项目。
实际用途:后续根据项目类型,创建对应Spring上下文容器,避免容器类型不匹配报错,保证Web容器、上下文、环境一一适配。
核心功能:区分三种项目类型:Servlet Web项目、Reactive响应式项目、非Web普通Java项目。
实际用途:后续根据项目类型,创建对应Spring上下文容器,避免容器类型不匹配报错。
2.3 步骤3:SPI加载初始化器(ApplicationContextInitializer)
步骤原理 :基于Spring SPI机制,读取META-INF/spring.factories配置文件,加载所有预定义的上下文初始化器,通过反射实例化并排序注册。
核心源码(SPI加载工厂实例核心方法)
// SPI统一加载核心方法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[0]);
}
// 完整SPI加载逻辑
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取当前类加载器
ClassLoader classLoader = getClassLoader();
// 1. 从spring.factories读取对应接口的所有实现类全限定名
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 2. 反射创建实例对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 3. 根据@Order注解排序,保证执行顺序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
核心功能 :在Spring上下文刷新之前,对上下文环境、属性、配置进行预处理,提前初始化全局配置、属性源、环境变量。
实际用途:完成环境参数初始化、配置校验、元数据初始化等前置操作,支撑容器正常启动。
拓展知识点 :SpringBoot2.x基于spring.factories实现SPI加载,SpringBoot3.x全新变更 :废弃spring.factories,改用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports实现自动加载,是版本核心变动点。
核心功能 :在Spring上下文刷新之前,对上下文环境、属性、配置进行预处理。
实际用途:完成环境参数初始化、配置校验、元数据初始化等前置操作,支撑容器正常启动。
拓展知识点 :SpringBoot2.x基于spring.factories实现SPI加载,SpringBoot3.x全新变更 :废弃spring.factories,改用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports实现自动加载,是版本核心变动点。
2.4 步骤4:SPI加载事件监听器(ApplicationListener)
步骤原理 :复用上方统一SPI加载方法,批量加载ApplicationListener所有实现类,注册为全局监听器,全程监听启动生命周期事件。
核心源码(监听器注册逻辑)
// 加载监听器并注册到全局
private void setListeners(Collection<ApplicationListener<?>> listeners) {
// 清空原有监听器,重新赋值,保证唯一性
this.listeners = new ArrayList<>(listeners);
}
核心功能:监听启动全流程所有节点事件,触发日志打印、配置加载、环境初始化、异常捕获、自定义拓展等操作。
实际用途:实现启动流程解耦,所有拓展功能通过监听器实现,无需修改核心启动源码,符合开闭原则。
核心功能:监听启动全流程所有节点事件,触发日志打印、配置加载、环境初始化、异常捕获等操作。
实际用途:实现启动流程解耦,所有拓展功能通过监听器实现,无需修改核心启动源码。
2.5 步骤5:推断主启动类
步骤原理:遍历当前线程堆栈信息,匹配包含main方法的类,精准定位项目启动主类。
核心源码(推断主类核心逻辑)
private Class<?> deduceMainApplicationClass() {
try {
// 获取当前线程堆栈轨迹
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
// 遍历堆栈,查找包含main方法的类
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// 忽略异常,无主类场景极少
}
return null;
}
核心功能:记录项目入口类,用于后续日志打印、配置扫描、Bean加载定位、自动配置扫描根路径。
实际用途 :确定SpringBoot自动扫描的根路径,默认扫描主类所在包及子包所有组件,是SpringBoot自动扫描机制的核心前提。
核心功能:记录项目入口类,用于后续日志打印、配置扫描、Bean加载定位。
实际用途:确定SpringBoot自动扫描的根路径,默认扫描主类所在包及子包所有组件。
2.6 第一阶段整体流程总结
创建SpringApplication实例 → 初始化资源加载器与主类集合 → 预判项目Web类型 → SPI加载上下文初始化器 → SPI加载全局事件监听器 → 定位主启动类。 本阶段无容器创建、无Bean加载,仅完成全局组件预加载与环境预判,为后续核心启动流程铺路。
三、第二阶段:run方法核心启动源码逐行拆解(核心重点)
阶段核心定位:SpringBoot项目真正启动的核心链路,所有容器创建、事件发布、环境加载、Bean初始化、Web容器启动全部在本阶段完成。
3.1 步骤1:启动计时与Headless模式配置
步骤原理:初始化计时器统计项目启动耗时,配置Java Headless无头模式,适配服务器无图形化环境启动。
核心功能:记录启动耗时、规避服务器图形化环境缺失导致的启动异常。
实际用途:生产服务器无桌面环境,开启Headless模式保证项目正常启动。
3.2 步骤2:加载运行监听器、发布首个启动事件
步骤原理 :加载SpringApplicationRunListener运行监听器,调用starting()方法,发布项目首个启动事件。
核心功能:触发启动前置监听逻辑,初始化运行链路监听组件。
实际用途:自定义启动前置拓展逻辑可在此事件实现。
public ConfigurableApplicationContext run(String... args) {
// 1. 启动计时器,统计项目整体启动耗时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 声明上下文容器、异常报告器集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 2. 配置Headless无头模式,适配服务器无图形化环境
configureHeadlessProperty();
// 3. 加载运行阶段专属监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 发布项目第一个启动事件:ApplicationStartingEvent
listeners.starting();
try {
// 后续步骤分步拆解
} catch (Throwable ex) {
// 全局启动异常兜底处理
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
}
步骤源码补充说明 :本步骤是run方法启动第一执行链路,完成耗时统计、环境适配、监听器初始化、首个事件发布,无任何业务与容器初始化操作,属于启动前置监听铺垫。
3.3 步骤3:命令行参数解析与环境准备
步骤原理:解析命令行启动参数,加载系统环境、JVM参数、外部配置文件,整合为标准化可配置环境对象,绑定到Spring上下文。
核心源码(环境准备核心方法)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 1. 根据项目类型创建对应环境对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 2. 配置环境参数:激活配置、命令行参数、系统变量
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 3. 绑定配置属性,刷新属性源
ConfigurationPropertySources.attach(environment);
// 4. 发布环境准备完成事件,触发配置加载、日志初始化
listeners.environmentPrepared(environment);
// 5. 绑定环境配置到SpringApplication
bindToSpringApplication(environment);
return environment;
}
核心功能:加载系统环境变量、JVM参数、yml/properties配置文件、命令行参数,整合为统一环境对象。
实际用途:为后续容器初始化、Bean属性注入、配置绑定、自动配置判断提供完整环境数据。
关键事件触发 :环境准备完成后,发布ApplicationEnvironmentPreparedEvent事件,触发配置文件加载、日志环境初始化等逻辑。
核心功能:加载系统环境变量、JVM参数、yml/properties配置文件、命令行参数,整合为统一环境对象。
实际用途:为后续容器初始化、Bean属性注入、配置绑定提供完整环境数据。
关键事件触发 :环境准备完成后,发布ApplicationEnvironmentPreparedEvent事件,触发配置文件加载、日志环境初始化等逻辑。
3.4 步骤4:打印Banner横幅、初始化异常报告器
步骤原理:基于已初始化的环境对象读取Banner配置,优先加载自定义Banner,无自定义则使用默认SpringBoot横幅,同时SPI加载启动异常报告器。
核心源码(Banner打印核心)
private Banner printBanner(ConfigurableEnvironment environment) {
// 关闭Banner打印则直接返回空
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
// 获取资源加载器、打印输出流
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(null);
// 创建Banner打印实例并执行打印
new BannerPrinter(environment, resourceLoader, System.out).print();
return new PrintedBanner();
}
核心功能:美化启动界面、捕获并格式化启动异常信息、收集启动报错处理器。
实际用途:便于开发者识别项目版本、快速定位启动报错信息,统一异常输出格式。
核心功能:美化启动界面、捕获并格式化启动异常信息。
实际用途:便于开发者识别项目版本、快速定位启动报错信息。
3.5 步骤5:创建Spring应用上下文
步骤原理:根据前期预判的WebApplicationType类型,反射创建对应类型的Spring IoC上下文容器,区分Web/非Web环境。
核心源码(创建上下文核心逻辑)
protected ConfigurableApplicationContext createApplicationContext() {
// 根据Web类型获取对应上下文Class对象
Class<? extends ConfigurableApplicationContext> contextClass = this.applicationContextClass;
if (contextClass == null) {
switch (this.webApplicationType) {
case SERVLET:
contextClass = AnnotationConfigServletWebServerApplicationContext.class;
break;
case REACTIVE:
contextClass = AnnotationConfigReactiveWebServerApplicationContext.class;
break;
case NONE:
default:
contextClass = AnnotationConfigApplicationContext.class;
}
}
// 反射实例化上下文容器
return BeanUtils.instantiateClass(contextClass);
}
核心功能 :Servlet项目创建AnnotationConfigServletWebServerApplicationContext,响应式项目创建对应容器,普通项目创建标准容器。
实际用途:初始化IoC容器顶层对象,为后续Bean加载、容器刷新、组件注册提供唯一载体。
核心功能 :Servlet项目创建AnnotationConfigServletWebServerApplicationContext,响应式项目创建对应容器,普通项目创建标准容器。
实际用途:初始化IoC容器顶层对象,为后续Bean加载、容器刷新提供载体。
3.6 步骤6:上下文预初始化(prepareContext)
步骤原理:容器刷新前置预处理,完成环境绑定、初始化器执行、资源注册、主类加载、事件发布,补全容器所有前置配置。
核心源码(prepareContext预处理核心)
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 绑定环境到上下文
context.setEnvironment(environment);
// 2. 后置处理上下文容器
postProcessApplicationContext(context);
// 3. 执行所有ApplicationContextInitializer初始化器
applyInitializers(context);
// 发布上下文初始化完成事件
listeners.contextPrepared(context);
// 4. 注册启动参数、Banner资源为单例Bean
if (this.logStartupInfo) {
logStartupInfo(true);
}
context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// 5. 加载主启动类、配置资源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// 发布配置加载完成事件
listeners.contextLoaded(context);
}
核心功能:完成上下文属性填充、组件注册、配置加载,禁止Bean重复覆盖、支持全局懒加载配置。
实际用途:完成容器刷新前的所有预处理,保证容器刷新顺利执行,规避配置缺失、环境不匹配问题。
关键事件触发 :上下文初始化完成发布ApplicationContextInitializedEvent ;加载主配置类后发布ApplicationPreparedEvent。
核心功能:完成上下文属性填充、组件注册、配置加载,禁止Bean重复覆盖、支持全局懒加载配置。
实际用途:完成容器刷新前的所有预处理,保证容器刷新顺利执行。
关键事件触发 :上下文初始化完成发布ApplicationContextInitializedEvent ;加载主配置类后发布ApplicationPreparedEvent。
3.7 步骤7:核心------容器刷新(refreshContext)
步骤原理:调用Spring原生refresh()核心方法,执行完整IoC容器刷新链路,包含Bean扫描、实例化、依赖注入、后置处理、Web容器启动,是SpringBoot启动最核心、最耗时环节。
核心源码(容器刷新入口)
private void refreshContext(ConfigurableApplicationContext context) {
// 开启或关闭刷新功能
if (this.refresh) {
// 执行Spring核心容器刷新方法
context.refresh();
}
}
refresh()底层核心执行链路:
-
刷新前准备:初始化容器状态、属性配置
-
加载Bean定义、扫描所有组件
-
执行Bean工厂后置处理器(加载自动配置类)
-
注册、执行Bean后置处理器
-
实例化单例Bean、完成依赖注入
-
初始化内置Tomcat/Web容器
-
发布容器刷新完成事件
核心功能:加载自动配置类、扫描所有Bean、实例化Bean、依赖注入、初始化后置处理器、启动内置Tomcat容器。
实际用途:完成所有业务组件、框架组件的初始化,启动Web服务,项目具备HTTP访问能力。
拓展知识点:自动配置的核心逻辑全部封装在refresh流程中,通过SPI加载自动配置类,按需装配框架组件,实现零配置启动。
核心功能:加载自动配置类、扫描所有Bean、实例化Bean、依赖注入、初始化后置处理器、启动内置Tomcat容器。
实际用途:完成所有业务组件、框架组件的初始化,启动Web服务,项目具备访问能力。
拓展知识点:自动配置的核心逻辑全部封装在refresh流程中,通过SPI加载自动配置类,按需装配框架组件,实现零配置启动。
3.8 步骤8:容器刷新后置处理与事件发布
步骤原理:容器刷新完成后执行拓展回调,结束启动计时、打印启动日志、发布启动成功事件,完成启动链路收尾。
核心源码(后置处理+事件发布)
// 刷新后置拓展
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
}
// 启动收尾、事件发布
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 发布容器启动完成事件
listeners.started(context);
// 执行自定义Runner:ApplicationRunner、CommandLineRunner
callRunners(context, applicationArguments);
核心功能:收尾启动流程、统计启动耗时、标记项目启动成功、执行自定义启动任务。
实际用途:告知开发者项目启动完成,同时触发自定义启动后置拓展逻辑、执行初始化任务。
关键事件触发 :发布ApplicationStartedEvent、服务就绪事件、流量接收事件,标记项目可正常处理请求。
核心功能:收尾启动流程、统计启动耗时、标记项目启动成功。
实际用途:告知开发者项目启动完成,同时触发自定义启动后置拓展逻辑。
关键事件触发 :发布ApplicationStartedEvent、服务就绪事件、流量接收事件,标记项目可正常处理请求。
3.9 步骤9:项目就绪、持续运行
步骤原理:所有启动流程执行完毕后,发布running就绪事件,容器持续监听端口、阻塞主线程,持续处理客户端请求。
核心源码(项目就绪收尾)
try {
// 发布项目运行就绪事件,正式对外提供服务
listeners.running(context);
} catch (Throwable ex) {
// 就绪阶段异常兜底
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
核心功能:完成项目最终就绪,进入常驻运行状态。
实际用途:项目正式对外提供服务,持续监听端口、处理HTTP请求。
核心功能:完成项目最终就绪,进入运行状态。
实际用途:项目正式对外提供服务。
3.10 run方法整体核心源码汇总
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 1. 加载运行监听器,发布启动开始事件
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 解析命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 2. 准备环境、加载配置文件
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印启动Banner
Banner printedBanner = printBanner(environment);
// 3. 创建Spring上下文容器
context = createApplicationContext();
// 初始化异常报告器
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ConfigurableApplicationContext.class}, context);
// 4. 预初始化上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 5. 核心:刷新IoC容器、启动Web服务
refreshContext(context);
// 6. 后置拓展处理
afterRefresh(context, applicationArguments);
// 结束计时、打印启动日志
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 发布启动完成事件
listeners.started(context);
// 执行自定义运行器
callRunners(context, applicationArguments);
} catch (Throwable ex) {
// 全局启动异常处理
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 发布运行就绪事件
listeners.running(context);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
特殊备注:该文中的示例代码为源代码整理后抽取部分核心点的代码作为理解展示,非真实源码,要看源码请自行根据方法名 / 类名前往对应的源码文件查看
整体启动流程可以简略如下图所示:

四、SpringBoot启动八大事件完整顺序详解
SpringBoot启动全程严格按照固定顺序发布事件,所有拓展功能、插件、监控、配置加载均依赖事件驱动,是底层核心设计,也是高频面试考点。
4.1 完整事件触发顺序与作用
-
ApplicationStartingEvent:项目启动最早期事件,仅完成监听器注册,无任何资源加载;
-
ApplicationEnvironmentPreparedEvent:环境准备完成,配置文件、系统环境加载完毕;
-
ApplicationContextInitializedEvent:Spring上下文初始化完成,属性、环境、参数全部绑定;
-
ApplicationPreparedEvent:主配置类加载完成,容器即将进入刷新阶段;
-
ApplicationStartedEvent:IoC容器刷新完成、Web容器启动成功,项目启动完成;
-
AvailabilityChangeEvent(LivenessState.CORRECT):标记应用存活、服务正常运行;
-
ApplicationReadyEvent:项目完全就绪,可接收处理客户端请求;
-
AvailabilityChangeEvent(ReadinessState.ACCEPTING_TRAFFIC):正式接收流量、对外提供服务。
异常专属事件 :项目启动报错时,触发ApplicationFailedEvent,执行异常日志打印、资源释放、故障记录。
五、关键易混淆知识点+生产踩坑拓展
5.1 SpringBoot2.x与3.x SPI机制差异(重点变更)
2.x版本:通过spring.factories文件实现SPI自动加载; 3.x版本:废弃spring.factories,采用AutoConfiguration.imports新机制,加载效率更高、配置更规范,旧项目升级需适配修改。
5.2 容器创建与刷新的区别
容器创建:仅初始化空容器对象,无Bean、无配置、无服务; 容器刷新:完成所有Bean加载、自动配置装配、Web容器启动,是项目真正启动的核心步骤。
5.3 启动事件自定义拓展场景
可通过自定义监听器监听启动事件,实现:启动日志定制、环境参数校验、项目启动通知、初始化数据加载、权限预校验等拓展功能,无侵入改造原生启动流程。
六、全文整体流程终极总结
-
启动前置阶段:执行main方法 → 创建SpringApplication实例 → 预判项目类型 → SPI加载初始化器、监听器 → 定位主启动类,完成全局组件预加载;
-
核心启动阶段:执行run方法 → 开启启动计时、配置无头模式 → 发布启动事件 → 解析命令行参数、加载环境与配置文件 → 打印Banner → 创建对应类型Spring容器 → 预初始化上下文、绑定配置与资源 → 刷新IoC容器(加载Bean、自动配置、启动Tomcat) → 后置处理、统计启动耗时;
-
就绪收尾阶段:依次发布启动完成、服务存活、流量接收事件 → 项目进入运行状态,持续处理客户端请求;
-
核心设计思想:基于SPI扩展机制+事件驱动机制,实现启动流程解耦、自动配置零冗余、高拓展性,是SpringBoot优于传统SSM的核心底层原理。