1. SpringBoot启动流程全景概览
SpringBoot的启动过程远比表面看到的SpringApplication.run()复杂得多。通过源码分析,我们可以将其拆解为七个关键阶段:
- 初始化阶段:创建SpringApplication实例
- 环境准备阶段:配置运行环境
- 上下文创建阶段:初始化应用上下文
- 前置处理阶段:执行ApplicationContextInitializer
- Bean加载阶段:执行BeanDefinition加载
- 后置处理阶段:执行ApplicationRunner/CommandLineRunner
- 启动完成阶段:发布ApplicationReadyEvent
每个阶段都包含若干精妙的设计,接下来我们将深入每个环节的源码实现。
2. SpringApplication初始化过程
2.1 构造方法核心逻辑
SpringApplication的构造方法主要完成三项工作:
java复制public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
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));
this.mainApplicationClass = deduceMainApplicationClass();
}
关键点解析:
webApplicationType通过类路径推断确定应用类型(Servlet/Reactive/None)- 通过
getSpringFactoriesInstances加载所有META-INF/spring.factories中定义的扩展类 mainApplicationClass通过堆栈分析确定主启动类
2.2 初始化器(Initializer)加载机制
SpringBoot通过SPI机制加载初始化器,核心代码如下:
java复制private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
这个机制使得我们可以通过简单的配置文件实现组件扩展,是SpringBoot"约定优于配置"理念的重要体现。
3. 环境准备与环境差异处理
3.1 环境配置的核心流程
环境准备阶段主要完成以下工作:
- 根据
webApplicationType创建对应环境对象 - 配置PropertySources(包括默认配置和用户配置)
- 处理Profile激活逻辑
- 转换环境属性(如将占位符替换为实际值)
关键源码片段:
java复制public ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建环境对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 发布环境准备事件
listeners.environmentPrepared(environment);
// 绑定环境到SpringApplication
bindToSpringApplication(environment);
// 环境后处理
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
return environment;
}
3.2 多环境支持实现原理
SpringBoot通过spring.profiles.active属性支持多环境配置,其核心处理逻辑在Environment接口的实现类中:
java复制public class StandardEnvironment extends AbstractEnvironment {
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(
new PropertiesPropertySource("systemProperties", getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource("systemEnvironment", getSystemEnvironment()));
}
}
实际开发中常见的多环境配置方案:
- 通过
application-{profile}.properties文件区分 - 使用
@Profile注解条件化加载Bean - 通过启动参数动态指定激活的Profile
4. 应用上下文创建与准备
4.1 上下文类型选择策略
SpringBoot根据应用类型自动选择适当的应用上下文:
java复制protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
// 默认实现
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
switch (webApplicationType) {
case SERVLET:
return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
return new AnnotationConfigReactiveWebServerApplicationContext();
default:
return new AnnotationConfigApplicationContext();
}
}
catch (Exception ex) {
throw new IllegalStateException(...);
}
};
4.2 上下文准备关键步骤
上下文准备阶段完成以下核心工作:
- 设置环境配置
- 后置处理Bean定义
- 执行初始化器
- 注册主配置类
关键源码:
java复制private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置环境
context.setEnvironment(environment);
// 后置处理
postProcessApplicationContext(context);
// 执行初始化器
applyInitializers(context);
// 发布上下文准备事件
listeners.contextPrepared(context);
// 注册启动参数Bean
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
// 注册打印的Banner
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// 注册主配置类
Set<Object> sources = getAllSources();
load(context, sources.toArray(new Object[0]));
// 发布上下文加载事件
listeners.contextLoaded(context);
}
5. Bean加载与自动配置机制
5.1 Bean定义加载过程
SpringBoot通过BeanDefinitionLoader加载Bean定义:
java复制protected void load(ApplicationContext context, Object[] sources) {
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
loader.setBeanNameGenerator(this.beanNameGenerator);
loader.setResourceLoader(this.resourceLoader);
loader.setEnvironment(this.environment);
loader.load();
}
加载过程会处理多种配置源:
- 注解配置类(@Configuration)
- XML配置
- Groovy脚本
- 包扫描路径
5.2 自动配置实现原理
自动配置的核心是@EnableAutoConfiguration注解,其处理流程如下:
- 从
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports加载自动配置类 - 过滤掉不符合条件的配置类(通过
@Conditional系列注解) - 按顺序应用有效的自动配置
关键源码片段:
java复制public void autoConfigurations(List<String> configurations) {
configurations.addAll(loadFactoryNames());
configurations.sort(AnnotationAwareOrderComparator.INSTANCE);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusion);
}
6. 启动后处理与扩展点
6.1 Runner接口执行机制
SpringBoot提供了两种Runner接口用于启动后执行特定逻辑:
ApplicationRunnerCommandLineRunner
它们的执行顺序如下:
java复制private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
6.2 事件发布机制
SpringBoot的启动过程通过事件机制实现高度扩展性,主要事件包括:
ApplicationStartingEvent:启动开始时触发ApplicationEnvironmentPreparedEvent:环境准备完成后触发ApplicationContextInitializedEvent:上下文初始化后触发ApplicationPreparedEvent:Bean加载前触发ApplicationStartedEvent:启动完成后触发ApplicationReadyEvent:应用完全就绪后触发
事件监听器的典型实现:
java复制public class MyListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// 应用就绪后执行的逻辑
}
}
7. 性能优化与常见问题排查
7.1 启动性能优化建议
- 组件懒加载:使用
@Lazy注解延迟初始化非关键Bean - 排除不必要的自动配置:通过
exclude属性禁用不需要的自动配置 - 优化组件扫描路径:精确指定
@ComponentScan的basePackages - 使用SpringFu:对于Kotlin项目,考虑使用函数式配置方式
- JVM参数调优:适当增加元空间大小(-XX:MaxMetaspaceSize)
7.2 常见启动问题排查
问题1:Bean循环依赖
解决方案:
- 重构代码消除循环依赖
- 使用
@Lazy延迟加载其中一个Bean - 使用setter注入替代构造器注入
问题2:自动配置冲突
排查步骤:
- 启用debug日志:
--debug参数启动应用 - 查看条件评估报告
- 检查是否有多个自动配置类提供了相同功能的Bean
问题3:Profile不生效
检查点:
- 确保
spring.profiles.active设置正确 - 检查配置文件命名是否符合
application-{profile}.properties格式 - 验证
@Profile注解使用是否正确
8. 高级特性与自定义扩展
8.1 自定义启动器(Starter)开发
开发自定义Starter的关键步骤:
- 创建
autoconfigure模块 - 编写自动配置类(带
@Configuration) - 添加条件注解(如
@ConditionalOnClass) - 在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中注册配置类 - 创建
starter模块并依赖autoconfigure
8.2 自定义Banner实现
实现自定义Banner的几种方式:
- 在
resources目录下添加banner.txt - 实现
Banner接口并通过SpringApplication.setBanner()设置 - 使用图片Banner(需配置
banner.image.location)
示例代码:
java复制public class MyBanner implements Banner {
@Override
public void printBanner(Environment environment,
Class<?> sourceClass, PrintStream out) {
out.println("=== 自定义Banner ===");
out.println("启动时间: " + new Date());
}
}
// 设置自定义Banner
SpringApplication app = new SpringApplication(MyApp.class);
app.setBanner(new MyBanner());
app.run(args);
8.3 自定义启动生命周期监听
通过实现SpringApplicationRunListener接口可以深度介入启动过程:
java复制public class MyRunListener implements SpringApplicationRunListener {
public MyRunListener(SpringApplication application, String[] args) {
// 初始化逻辑
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
// 启动开始时的逻辑
}
// 实现其他生命周期方法...
}
// 通过META-INF/spring.factories注册
org.springframework.boot.SpringApplicationRunListener=\
com.example.MyRunListener
9. 新版特性与未来演进
SpringBoot 3.0以来的重要改进:
- GraalVM原生镜像支持:通过Spring Native项目实现
- JDK17基线要求:充分利用新JDK特性
- 改进的自动配置:更细粒度的条件控制
- 增强的观察ability:与Micrometer深度集成
- 记录器(Lazy Logging):延迟日志初始化提升启动速度
未来可能的发展方向:
- 更深入的云原生支持
- 与Project Loom的虚拟线程集成
- 更智能的自动配置决策
- 增强的AOT编译支持
