Spring Boot启动流程及源码实现深度解析
Spring Boot启动流程及源码实现深度解析
一、启动流程概述
Spring Boot的启动流程围绕SpringApplication
类展开,核心流程可分为以下几个阶段:
- 初始化阶段:推断应用类型,加载
ApplicationContextInitializer
和ApplicationListener
- 环境准备:加载配置文件和命令行参数
- 上下文创建:实例化
ApplicationContext
- 上下文刷新:执行
refresh()
方法完成Bean加载 - 后置处理:执行
CommandLineRunner
和ApplicationRunner
二、源码解析
1. 入口类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
2. SpringApplication初始化
// SpringApplication.java
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return new SpringApplication(primarySource).run(args);
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
private SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 推断应用类型
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class)); // 加载Initializers
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 加载Listeners
this.mainApplicationClass = deduceMainApplicationClass();
}
关键步骤解析:
deduceFromClasspath()
通过类路径判断应用类型(Servlet/Reactive/None)- 从
META-INF/spring.factories
加载初始化器和监听器
3. run()方法核心流程
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
// 创建应用上下文
context = createApplicationContext();
context.setEnvironment(environment);
// 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文(核心)
refreshContext(context);
// 后置处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
// 发布启动完成事件
listeners.started(context);
callRunners(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
listeners.running(context);
return context;
}
三、关键阶段详解
1. 环境准备(prepareEnvironment)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment); // 发布环境准备事件
bindToSpringApplication(environment);
return environment;
}
- 加载
application.properties/yml
文件 - 处理命令行参数
--
开头的参数 - 触发
ApplicationEnvironmentPreparedEvent
事件
2. 上下文创建(createApplicationContext)
根据应用类型创建不同的上下文:
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(...);
}
};
3. 上下文刷新(refreshContext)
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
} catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
protected void refresh(ApplicationContext applicationContext) {
((AbstractApplicationContext) applicationContext).refresh();
}
最终调用AbstractApplicationContext.refresh()
,这是Spring容器的核心方法:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
// ... [省略其他步骤]
finishRefresh(); // 触发ContextRefreshedEvent
}
}
四、关键扩展点
1. ApplicationContextInitializer
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
- 执行时机:上下文准备阶段(prepareContext)
- 配置方式:通过
spring.factories
或SpringApplication.addInitializers()
2. ApplicationRunner/CommandLineRunner
@Component
public class DemoRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) {
// 应用启动后执行
}
}
- 执行顺序:通过
@Order
注解控制 - 执行时机:上下文刷新完成后
五、总结
Spring Boot的启动流程通过智能的自动配置和扩展机制,显著简化了Spring应用的初始化过程。理解其核心流程和关键扩展点,可以帮助开发者:
- 深入排查启动过程中的问题
- 实现自定义的初始化逻辑
- 优化应用启动性能
- 扩展框架的核心功能
建议结合源码调试工具,通过断点跟踪SpringApplication.run()
的执行过程,可以更直观地理解各阶段的实现细节。
流程图文字描述:
main()
└─▶ SpringApplication.run()
├─▶ 初始化应用类型和扩展组件
├─▶ 准备环境(加载配置)
├─▶ 创建ApplicationContext
├─▶ 准备上下文(Bean定义加载)
├─▶ 刷新上下文(Bean初始化)
├─▶ 执行Runner接口
└─▶ 完成启动
通过以上分析,读者可以系统地掌握Spring Boot的启动机制及其实现原理。实际开发中可结合具体需求,合理使用扩展点进行定制化开发。