Spring Boot 的启动流程是一个精心设计的过程,它简化了传统 Spring 应用的配置和部署。下面详细分析整个启动过程。
0. 完整的启动流程图解
启动入口
↓
创建 SpringApplication 实例
↓ → 推断应用类型
↓ → 加载 Initializers
↓ → 加载 Listeners
运行 SpringApplication
↓ → 启动计时器
↓ → 创建引导上下文
↓ → 获取运行监听器
↓ → 发布启动事件
准备环境
↓ → 创建环境对象
↓ → 配置环境
↓ → 发布环境准备事件
创建应用上下文
↓ → 根据类型创建对应上下文
准备上下文
↓ → 设置环境
↓ → 应用初始化器
↓ → 发布上下文事件
↓ → 加载 Bean 定义
刷新上下文(核心)
↓ → prepareRefresh()
↓ → obtainFreshBeanFactory()
↓ → prepareBeanFactory()
↓ → postProcessBeanFactory()
↓ → invokeBeanFactoryPostProcessors()
↓ → registerBeanPostProcessors()
↓ → initMessageSource()
↓ → initApplicationEventMulticaster()
↓ → onRefresh() ← 创建 Web 服务器
↓ → registerListeners()
↓ → finishBeanFactoryInitialization() ← 初始化单例 Bean
↓ → finishRefresh()
后置处理
↓ → 发布启动完成事件
↓ → 执行 Runner 接口
↓ → 发布就绪事件
启动完成
1. 启动入口
标准的 Spring Boot 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. 启动流程详细步骤
整体流程图
1. 启动入口 → 2. 创建SpringApplication实例 → 3. 运行SpringApplication
↓
4. 准备环境 → 5. 创建应用上下文 → 6. 准备上下文
↓
7. 刷新上下文 → 8. 后置处理 → 9. 启动完成
详细步骤分解
步骤1: 创建 SpringApplication 实例
public class SpringApplication {
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = deduceWebApplicationType();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
}
这个阶段主要完成:
-
推断应用类型(Servlet、Reactive、None)
-
加载
BootstrapRegistryInitializer -
加载
ApplicationContextInitializer -
加载
ApplicationListener -
推断主应用类
步骤2: 运行 SpringApplication
public ConfigurableApplicationContext run(String... args) {
// 1. 启动计时器
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2. 创建引导上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
// 3. 配置 headless 属性
configureHeadlessProperty();
// 4. 获取运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 5. 发布应用启动事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 6. 准备应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 7. 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 8. 配置忽略的 Bean 信息
configureIgnoreBeanInfo(environment);
// 9. 打印 Banner
Banner printedBanner = printBanner(environment);
// 10. 创建应用上下文
context = createApplicationContext();
// 11. 准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 12. 刷新上下文(核心步骤)
refreshContext(context);
// 13. 后置处理
afterRefresh(context, applicationArguments);
// 14. 停止计时器
stopWatch.stop();
// 15. 发布应用启动完成事件
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
// 16. 调用 ApplicationRunner 和 CommandLineRunner
callRunners(context, applicationArguments);
// 17. 发布应用运行中事件
listeners.ready(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
return context;
}
3. 核心步骤详解
3.1 环境准备 (prepareEnvironment)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 创建环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 绑定环境到 SpringApplication
ConfigurationPropertySources.attach(environment);
// 发布环境准备事件
listeners.environmentPrepared(bootstrapContext, environment);
return environment;
}
3.2 创建应用上下文 (createApplicationContext)
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}
// 根据应用类型创建不同的上下文
// - SERVLET: AnnotationConfigServletWebServerApplicationContext
// - REACTIVE: AnnotationConfigReactiveWebServerApplicationContext
// - NONE: AnnotationConfigApplicationContext
3.3 准备上下文 (prepareContext)
private void prepareContext(DefaultBootstrapContext bootstrapContext, 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);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// 加载 Bean 定义
load(context, sources.toArray(new Object[0]));
// 发布上下文加载事件
listeners.contextLoaded(context);
}
3.4 刷新上下文 (refreshContext) - 核心中的核心
private void refreshContext(ConfigurableApplicationContext context) {
// 委托给 refresh 方法
refresh(context);
}
protected void refresh(ApplicationContext applicationContext) {
// 调用 AbstractApplicationContext.refresh()
applicationContext.refresh();
}
Spring 上下文的刷新过程:
// 在 AbstractApplicationContext 中
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新上下文
prepareRefresh();
// 2. 获取新的 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory
prepareBeanFactory(beanFactory);
try {
// 4. 后置处理 BeanFactory
postProcessBeanFactory(beanFactory);
// 5. 调用 BeanFactory 后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 Bean 后置处理器
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 初始化特殊 Bean(由子类实现)
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 完成 BeanFactory 初始化
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新
finishRefresh();
} catch (BeansException ex) {
// 处理异常...
}
}
}
3.5 Spring Boot 的 onRefresh() 方法
// 在 ServletWebServerApplicationContext 中
@Override
protected void onRefresh() {
super.onRefresh();
try {
// 创建 Web 服务器
createWebServer();
} catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
// 获取 WebServerFactory
ServletWebServerFactory factory = getWebServerFactory();
// 创建 WebServer
this.webServer = factory.getWebServer(getSelfInitializer());
} else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
} catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
// 初始化属性源
initPropertySources();
}
4. 自动配置原理
@SpringBootApplication 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
// ...
}
自动配置加载过程
// 在 SpringFactoriesLoader 中加载自动配置类
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
// 从 META-INF/spring.factories 加载配置
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryType.getName());
// 解析并返回配置类列表
}
}
5. 启动事件机制
启动事件序列
public class ApplicationStartingEvent extends SpringApplicationEvent {
// 应用启动事件
}
public class ApplicationEnvironmentPreparedEvent extends SpringApplicationEvent {
// 环境准备完成事件
}
public class ApplicationContextInitializedEvent extends SpringApplicationEvent {
// 上下文初始化事件
}
public class ApplicationPreparedEvent extends SpringApplicationEvent {
// 应用准备完成事件
}
public class ApplicationStartedEvent extends SpringApplicationEvent {
// 应用启动完成事件
}
public class ApplicationReadyEvent extends SpringApplicationEvent {
// 应用就绪事件
}
public class ApplicationFailedEvent extends SpringApplicationEvent {
// 应用启动失败事件
}
自定义启动监听器
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// 应用启动完成后执行
System.out.println("应用启动完成,可以开始处理业务逻辑");
}
}
6. Runner 接口的执行
ApplicationRunner 和 CommandLineRunner
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 在应用启动后执行
System.out.println("ApplicationRunner 执行");
}
}
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// 在应用启动后执行
System.out.println("CommandLineRunner 执行");
}
}
总结
Spring Boot 的启动流程是一个精心编排的过程,主要特点:
-
简化配置:通过自动配置减少 XML 配置
-
嵌入式容器:内置 Tomcat、Jetty 等 Web 服务器
-
事件驱动:通过事件机制实现扩展点
-
条件化装配:根据条件自动配置 Bean
-
健康检查:提供完善的应用健康监控
理解 Spring Boot 的启动流程对于排查启动问题、进行自定义扩展和优化应用性能都非常有帮助。
2万+

被折叠的 条评论
为什么被折叠?



