一文了解Spring Boot启动类SpringApplication

💡 原文中文,约9600字,阅读约需23分钟。
📝

内容提要

本文介绍了Spring Boot的启动类SpringApplication的源码和知识点,包括run方法的使用和其他功能。了解Spring Boot的启动过程对于理解其运行机制和解决问题很重要。

🔎

延伸解读

入口类不一定是 main 方法所在类

文章通过示例说明,决定 Spring Boot 自动配置是否开启的,是传入 SpringApplication 的 primarySources 是否被 @EnableAutoConfiguration 或其组合注解标注,而非 main 方法所在的类。因此可以将 main 方法保留在 DemoApplication 中,却传入 SecondApplication.class 作为引导类,应用依然能正常启动并完成自动配置。这为多模块或需要灵活指定配置入口的场景提供了便利。

Web 应用类型在启动前已确定

SpringApplication 构造时会调用 WebApplicationType.deduceFromClasspath() 推断应用类型。判断依据是类路径上是否存在特定类:若 DispatcherHandler 存在且 DispatcherServlet 与 ServletContainer 都不存在,则为 REACTIVE;若 Servlet 或 ConfigurableWebApplicationContext 任一缺失,则为 NONE;否则为 SERVLET。这一推断在容器刷新前完成,会影响后续启动流

启动早期扩展点的加载顺序

构造方法中依次加载并初始化 BootstrapRegistryInitializer、ApplicationContextInitializer 和 ApplicationListener。BootstrapRegistryInitializer 与 Spring Cloud Config 客户端初始化相关;ApplicationContextInitializer 在容器刷新前对 ConfigurableApplicationContext 做定制;ApplicationListener 基于观察者模式监听应用事

primarySources 使用 LinkedHashSet 的考量

构造方法将 primarySources 转为 LinkedHashSet,既保证元素唯一,又维护插入顺序,便于遍历。文章指出,LinkedHashSet 在频繁遍历时可能比 HashSet 更高效,但它是非线程安全的。由于启动阶段通常为单线程,这一选择在保证顺序的同时避免了重复配置类被多次处理,但若后续在多线程环境中访问该集合,则需注意并发问题。

❓

Q&A

SpringApplication的run方法有什么作用?

run方法用于启动整个Spring Boot项目,并返回一个应用上下文对象。

SpringApplication的构造方法有哪些参数?

构造方法有两个参数:ResourceLoader和primarySources,primarySources用于指定主要的bean来源。

如何推断Spring Boot应用的入口类?

通过调用deduceMainApplicationClass方法,遍历堆栈信息来找到包含main方法的类。

WebApplicationType是如何推断的?

通过deduceFromClasspath方法判断类的存在性来推断Web应用类型,包括非Web、基于Servlet和基于reactive的Web应用。

BootstrapRegistryInitializer的作用是什么?

BootstrapRegistryInitializer用于在应用程序启动时初始化Spring Cloud Config客户端。

ApplicationListener在Spring Boot中有什么用?

ApplicationListener用于实现事件监听机制,监控应用内部的运行状况,提升系统的可扩展性和可维护性。

🏷️

标签

➡️

继续阅读