Spring Boot自动装配、启动流程、配置优先级问题记录
作者:SpringHeather
问题 1:Spring Boot 自动装配的核心原理是什么?
Spring Boot 自动装配的核心依赖于 @EnableAutoConfiguration 注解(该注解被 @SpringBootApplication 组合注解包含,无需单独声明)。
核心流程:
- 注解驱动:
@EnableAutoConfiguration通过@Import(AutoConfigurationImportSelector.class)导入核心选择器类; - 扫描配置:
AutoConfigurationImportSelector借助SpringFactoriesLoader工具,扫描项目所有依赖包下的META-INF/spring.factories文件(Spring Boot 2.x 版本),该文件中配置了大量自动配置类全路径(如DataSourceAutoConfiguration、WebMvcAutoConfiguration); - 条件筛选:自动配置类需满足预设条件才会生效,核心依赖 Spring 条件注解(如
@ConditionalOnClass检查类路径是否存在指定类、@ConditionalOnMissingBean检查用户是否自定义同类型 Bean、@ConditionalOnProperty检查配置文件是否开启对应开关); - 配置生效:满足条件的自动配置类被 Spring 容器加载,完成 Bean 自动注册,实现“开箱即用”。
总结:Spring Boot 自动装配并非“全自动”,而是“有条件的自动装配”。核心是 @EnableAutoConfiguration 注解 + SpringFactoriesLoader 扫描机制 + 条件注解筛选的组合逻辑,既实现了简化配置,又保证了灵活可控。(注:Spring Boot 3.x 版本将自动配置类清单迁移至 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,核心逻辑不变)
问题 2:Spring Boot 应用的完整启动流程(尤其是 Web 项目)
Spring Boot 的启动流程可以拆分为两个核心阶段:初始化 SpringApplication 实例 和 执行 run() 方法
整个流程始终围绕三个核心目标展开:准备运行环境、创建并初始化应用上下文、启动核心业务逻辑
阶段一:执行 main 方法 & 初始化 SpringApplication
Spring Boot 应用的启动入口是 main 方法,核心调用为:
SpringApplication.run(Application.class, args);
在该调用中,首先会创建一个 SpringApplication 实例,并完成以下三件关键事情:
- 推断应用类型(Web / 非 Web / Reactive):通过检查类路径中是否存在
Servlet(Web 应用)、ReactiveWebApplicationContext(响应式应用)相关类来判定,决定后续创建的应用上下文类型; - 加载初始化器与监听器:从
META-INF/spring.factories中加载并实例化ApplicationContextInitializer(应用上下文初始化器)和ApplicationListener(应用事件监听器),这是后续自动装配和事件机制生效的关键前置步骤; - 记录主启动类:定位并存储 main 方法所在的启动类,为后续
@ComponentScan扫描配置类提供依据。
阶段二:执行 run() 方法(核心启动逻辑)
run() 方法是 Spring Boot 启动流程的核心入口,其内部按顺序完成以下五个关键步骤:
- 准备运行环境(Environment):加载命令行参数、JVM 系统属性、环境变量、application.yml/properties 等配置来源,封装为
ConfigurableEnvironment实例;并完成环境配置的校验与激活(如激活指定 Profile); - 创建应用上下文(ApplicationContext):根据阶段一推断的应用类型,创建对应类型的应用上下文(Web 应用默认创建
AnnotationConfigServletWebServerApplicationContext);将阶段一准备的环境对象绑定到上下文; - 刷新应用上下文(refresh()):这是启动流程的核心步骤,完成 Bean 定义加载、Bean 实例化与依赖注入、事件监听器注册等工作;对于 Web 项目,此阶段会调用
createWebServer()方法,通过ServletWebServerFactory工厂创建并启动嵌入式 Tomcat 服务器; - 执行启动后运行器(ApplicationRunner / CommandLineRunner):遍历 Spring 容器中所有实现这两个接口的 Bean,按顺序执行其
run()方法,用于执行启动后的初始化任务(如加载基础数据、打印启动日志);两者区别:ApplicationRunner接收解析后的ApplicationArguments对象,CommandLineRunner接收原始命令行字符串数组; - 发布应用就绪事件(ApplicationReadyEvent):通过事件机制发布应用就绪事件,标识应用已完全启动,此时应用进入运行状态,可正常接收并处理外部请求。
问题 3:Spring Boot Web 项目如何启动嵌入式 Web 服务器?
答:Spring Boot Web 项目的嵌入式 Web 服务器(默认 Tomcat),核心是在 应用上下文刷新(refresh())阶段 启动,具体流程如下:
- 依赖触发:项目引入
spring-boot-starter-web依赖时,Spring Boot 会通过自动装配机制,加载ServletWebServerFactoryAutoConfiguration自动配置类; - 工厂创建:该自动配置类会根据类路径中的 Web 服务器依赖(如 Tomcat、Jetty),自动注册对应的
ServletWebServerFactory工厂实例(默认注册TomcatServletWebServerFactory); - 上下文绑定:阶段二创建应用上下文时,Web 应用会使用
AnnotationConfigServletWebServerApplicationContext,该上下文内置了 Web 服务器启动逻辑; - 服务器启动:在
refresh()方法执行过程中,会调用createWebServer()方法,该方法通过ServletWebServerFactory工厂创建TomcatWebServer实例,内部调用tomcat.start()启动服务器;同时将项目中的 Servlet(如 DispatcherServlet)注册到服务器; - 就绪可用:服务器启动完成后,随应用就绪事件发布,开始监听指定端口(默认 8080),接收 HTTP 请求。
问题 4:Spring Boot 配置属性的优先级顺序
Spring Boot 支持多种外部配置来源,优先级明确(数字越小,优先级越高,后加载的配置会覆盖先加载的同名配置):
优先级 | 配置来源 | 示例 |
|---|---|---|
1 | 命令行参数 | --server.port=8081 |
2 | JVM 系统属性(-D 参数) | -Dserver.port=8082 |
3 | 操作系统环境变量 | Windows:set SERVER_PORT=8083;Linux/Mac:export SERVER_PORT=8083 |
4 | bootstrap.yml / bootstrap.properties(Spring Cloud 特有) | spring.application.name=cloud-demo |
5 | 远程配置中心(如 Spring Cloud Config Server) | spring.datasource.url=jdbc:mysql://xxx:3306/db |
6 | 激活的 Profile 配置文件(application-{profile}.yml / .properties) | application-prod.yml(需通过 spring.profiles.active=prod 激活) |
7 | 默认全局配置(application.yml / application.properties) | application.yml 中配置 server.port=8080 |
8 | @PropertySource 注解加载的自定义配置文件 | @PropertySource("classpath:custom.properties") |
9 | 应用代码中设置的默认值 | SpringApplication.setDefaultProperties(Collections.singletonMap("server.port", 8084)) |
Profile 规则:激活的 Profile 配置文件优先级高于默认全局配置,即 application-{profile}.yml / .properties > application.yml / .properties;若同时激活多个 Profile,后激活的 Profile 配置会覆盖先激活的。
问题 5:application.yml 和 application.properties 哪个优先级更高?
答:在 Spring Boot 中,application.yml 和 application.properties 属于同一优先级层级,当两者并存且存在同名配置时,后被 Spring 加载的配置会覆盖先加载的。
默认加载顺序:Spring Boot 会先加载 application.properties,再加载 application.yml,因此同名配置最终生效的是application.yml 的配置;但该顺序可通过自定义配置加载逻辑修改,核心原则是“同层级配置,后加载覆盖先加载”。
注意:若两者与 Profile 结合(如 application-prod.yml 和 application-prod.properties),规则相同——同一 Profile 下的 properties 和 yml 同优先级,后加载者覆盖先加载者。
问题 6:Spring Cloud 中的 bootstrap.yml 是什么?和 application.yml 有何区别?
答:
核心特性:bootstrap.yml 是 Spring Cloud 生态特有的启动级配置文件,基于 Spring Cloud 的“引导上下文(Bootstrap Context)”机制加载。引导上下文是应用主上下文的父上下文,优先级更高,主要用于加载应用启动过程中“必须提前准备的核心配置”(如远程配置中心地址、服务注册中心地址、应用名称等),确保这些配置在主上下文初始化前就绪。
与 application.yml 区别
特性 | bootstrap.yml | application.yml |
|---|---|---|
加载时机 | 引导上下文初始化前(应用启动最早期) | 应用主上下文初始化时 |
依赖机制 | 依赖 Spring Cloud 引导机制,无 Spring Cloud 依赖时不生效 | Spring Boot 原生支持,无需额外依赖 |
典型用途 | 1. 配置远程配置中心地址(spring.cloud.config.uri);2. 配置服务注册中心地址(eureka.client.serviceUrl.defaultZone);3. 定义应用名称(spring.application.name,用于服务发现和配置中心定位);4. 配置加密/解密密钥(用于解密配置中心的敏感配置) | 1. 应用端口(server.port);2. 数据库连接信息(spring.datasource.*);3. 日志配置(logging.*);4. 业务自定义属性(如 user.name) |
优先级 | 更高(覆盖同名的 application.yml 配置) | 更低(被 bootstrap.yml 同名配置覆盖) |
Profile 支持 | 支持 bootstrap-{profile}.yml,优先级:bootstrap-{profile}.yml > bootstrap.yml | 支持 application-{profile}.yml,优先级:application-{profile}.yml > application.yml |
到此这篇关于Spring Boot自动装配、启动流程、配置优先级问题记录的文章就介绍到这了,更多相关Spring Boot自动装配 启动流程 配置优先级内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
