Spring Boot 面试题笔记
个人复习笔记,覆盖 Spring Boot 自动配置、配置管理、Starter、部署运维的高频面试题。
目录
- [Spring Boot 基础认知](#Spring Boot 基础认知)
- 自动配置原理
- 配置管理
- [Starter 起步依赖](#Starter 起步依赖)
- [Web 开发相关](#Web 开发相关)
- 部署与运维
- 版本与生态
Spring Boot 基础认知
Spring Boot 解决了 Spring 的哪些痛点?
- 配置繁琐 → 自动配置(AutoConfiguration),按约定默认配好,需要时再覆盖;
- 依赖管理痛苦 → Starter 起步依赖 + parent 统一版本,不再为依赖冲突头疼;
- 部署麻烦 → 内嵌 Tomcat/Jetty/Undertow,打成可执行 jar 直接
java -jar启动,不用外置容器; - 生产级功能缺失 → Actuator 提供健康检查、指标、监控端点。
一句话:约定优于配置,让开发者专注业务。
@SpringBootApplication 包含哪三个注解?各有什么作用?(高频)
java
@SpringBootApplication
├── @SpringBootConfiguration // 本质是 @Configuration,标识配置类
├── @EnableAutoConfiguration // 开启自动装配(核心)
└── @ComponentScan // 扫描当前包及子包的组件
这也解释了为什么启动类要放在根包:@ComponentScan 默认扫启动类所在包及子包。
自动配置原理
自动配置的实现原理?(最高频)
按 Spring Boot 2.7+/3.x 的链路回答(2.7 以前文件名不同,原理一致):
@SpringBootApplication上的 @EnableAutoConfiguration 引入@Import(AutoConfigurationImportSelector.class);AutoConfigurationImportSelector从所有依赖 jar 包的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件里读出全部候选自动配置类(旧版本读META-INF/spring.factories);- 每个 XxxAutoConfiguration 类上大量使用条件注解 (@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty 等)按条件筛选:类路径有这个类、用户没自己配、配置开关打开......满足条件的才生效;
- 生效的配置类通过 @Bean 向容器注入默认组件(如 DataSource、RedisTemplate),用户自己定义的同类型 Bean 优先(@ConditionalOnMissingBean 让位)。
一句话总结:启动时按类路径扫描自动配置清单,再用条件注解过滤,把符合约定的 Bean 自动注册进容器。
常见的 @Conditional 条件注解有哪些?
| 注解 | 生效条件 |
|---|---|
@ConditionalOnClass |
类路径存在指定类 |
@ConditionalOnMissingClass |
类路径不存在指定类 |
@ConditionalOnBean |
容器中存在指定 Bean |
@ConditionalOnMissingBean |
容器中不存在指定 Bean(用户自定义优先的关键) |
@ConditionalOnProperty |
配置属性满足条件(如 havingValue) |
@ConditionalOnWebApplication |
是 Web 应用 |
@ConditionalOnResource |
类路径存在指定资源文件 |
如何排查某个自动配置类为什么没生效?
启动加 --debug(或配置 debug=true),启动日志输出 ConditionEvaluationReport:Positive matches(生效了,命中哪个条件)和 Negative matches(没生效,差哪个条件)。
如何排除某个自动配置?
java
// 方式一:注解排除
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
// 方式二:配置文件排除
// spring.autoconfigure.exclude=xxx.XxxAutoConfiguration
配置管理
配置文件的加载优先级?
从高到低(高优先级覆盖低优先级):
- 命令行参数
--server.port=8081 - JNDI / Java 系统属性 / 操作系统环境变量
- jar 包外部的
application-{profile}.yml→application.yml - jar 包内部的
application-{profile}.yml→application.yml
同目录下 properties 优先于 yml。外部配置优于内部,所以线上改外置配置即可,不用重新打包。
@Value 和 @ConfigurationProperties 的区别?
| @Value | @ConfigurationProperties | |
|---|---|---|
| 使用方式 | 一个个字段标 | 整个类批量绑定前缀 |
| 松散绑定 | 不支持(严格匹配) | 支持(my.name 可绑到 myName) |
| SpEL | 支持 | 不支持 |
| JSR303 校验 | 不方便 | 支持 @Validated + @NotBlank 等 |
| 适用场景 | 少量单个配置 | 一组相关配置(如整个邮件配置段) |
java
@Component
@ConfigurationProperties(prefix = "mail")
@Validated
public class MailProperties {
private String host;
private Integer port;
// getter/setter
}
多环境怎么配置?
yaml
spring:
profiles:
active: dev # 默认激活 dev
--- # yml 中用 --- 分割文档块
spring:
config:
activate:
on-profile: dev
server:
port: 8080
---
spring:
config:
activate:
on-profile: prod
server:
port: 80
启动时切换:java -jar app.jar --spring.profiles.active=prod。不同环境用 application-dev.yml / application-prod.yml 拆文件。
配置里的敏感信息(数据库密码)怎么处理?
- Jasypt 加密后存配置,启动时传解密密钥;
- 环境变量 / 启动参数注入;
- 用 Nacos/Apollo 等配置中心统一管理。
Starter 起步依赖
什么是 Starter?
一组依赖描述符 (pom 聚合)+ 自动配置 的封装。引入 spring-boot-starter-web 就等于引入了 web 开发所需的一整套依赖(Spring MVC、Jackson、内嵌 Tomcat),并自动完成配置,无需逐个声明版本。
命名约定:官方 starter 叫 spring-boot-starter-xxx;自定义的叫 xxx-spring-boot-starter。
如何自定义一个 Starter?(高频)
- 建两个模块(或一个):
xxx-spring-boot-autoconfigure:写自动配置类;xxx-spring-boot-starter:空工程,聚合依赖;
- 写核心服务类 + 配置属性类(@ConfigurationProperties);
- 写自动配置类,用条件注解控制生效:
java
@AutoConfiguration
@ConditionalOnClass(SmsService.class)
@ConditionalOnProperty(prefix = "sms", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsService smsService(SmsProperties props) {
return new SmsService(props);
}
}
- 在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(旧版 spring.factories)里登记该配置类; - 其他项目引入 starter,配好
sms.*配置即可直接注入 SmsService。
Web 开发相关
Spring Boot 的启动流程?
SpringApplication.run()→ 创建 SpringApplication 实例(推断应用类型、加载初始化器和监听器);- 准备 Environment(加载配置文件、环境变量);
- 创建并刷新 ApplicationContext(核心在 refresh():加载 BeanDefinition、执行 BeanFactoryPostProcessor、自动配置导入、实例化单例 Bean、启动 Web 服务器);
- 执行 ApplicationRunner / CommandLineRunner 回调;
- 发布启动完成事件,应用就绪。
Spring Boot 内嵌 Tomcat 是怎么启动的?
Servlet 容器不再以 war 包形式独立部署,而是作为应用里的一个对象:ServletWebServerFactoryAutoConfiguration 自动配置 TomcatServletWebServerFactory,容器刷新过程中调用其 getWebServer() 启动内嵌 Tomcat,并把 DispatcherServlet 注册进去。想换容器引入 spring-boot-starter-jetty/undertow、排除默认 tomcat 即可。
跨域怎么解决?
java
// 方式一:全局配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowCredentials(true);
}
}
// 方式二:@CrossOrigin 标在类/方法上
// 方式三:交给网关统一处理(微服务推荐)
接口参数校验怎么做?
spring-boot-starter-validation + JSR303 注解(@NotNull、@NotBlank、@Min、@Pattern 等),Controller 参数上加 @Valid / @Validated,配合全局异常处理器捕获 MethodArgumentNotValidException 返回友好提示。
部署与运维
Actuator 是什么?常用端点有哪些?
生产级监控端点集合,默认暴露部分端点,需在配置中放开:
| 端点 | 作用 |
|---|---|
/health |
健康检查(数据库、Redis 连通性聚合展示),配合 K8s 探针 |
/info |
应用信息 |
/metrics |
JVM、HTTP、系统各项指标 |
/env |
环境与配置属性(注意脱敏) |
/beans |
容器中所有 Bean |
/loggers |
运行时动态调整日志级别 |
/threaddump、/heapdump |
线程/堆快照排查问题 |
yaml
management:
endpoints:
web:
exposure:
include: health,info,metrics
生产上常配合 Spring Boot Admin 或 Prometheus + Grafana 做可视化监控。
优雅停机怎么配置?
yaml
server:
shutdown: graceful # 2.3+ 支持
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
效果:收到 kill 信号后不再接收新请求,等待存量请求处理完(或超时)再关闭容器,避免请求被硬切断。K8s 场景配合 preStop 钩子。
Spring Boot 打的是 jar,为什么能直接 java -jar 运行?
Spring Boot Maven/Gradle 插件打成可执行 fat jar :依赖的第三方 jar 全部放进 BOOT-INF/lib,应用类在 BOOT-INF/classes,由自定义的 JarLauncher + 自定义 URL 协议(jar:nested:)加载。区别于普通 jar 的地方在于 MANIFEST 里 Main-Class 指向 Launcher 而不是业务类。
版本与生态
Spring Boot 2.x 和 3.x 的主要区别?
- JDK 基线 :3.x 要求 Java 17+(2.x 是 Java 8+);
- Jakarta EE :包名从
javax.*迁移到jakarta.*(如 javax.servlet → jakarta.servlet),老代码升级要改 import; - Spring Framework 5 → 6,支持 AOT / GraalVM Native Image;
- 可观测性增强:原生集成 Micrometer Tracing(替代 Sleuth);
- 自动配置登记文件从 spring.factories(2.7 弃用)变为 AutoConfiguration.imports。
Spring Boot 和 Spring Cloud 的关系?
Spring Boot 是地基 (快速构建单个应用);Spring Cloud 是微服务全家桶(注册中心、配置中心、网关、熔断限流等),基于 Boot 的自动配置体系把各微服务组件整合起来。版本上有对应关系(Boot 3.x 配 Spring Cloud 2023.x/2024.x)。
Spring Boot 里 Bean 的默认初始化时机?想懒加载怎么办?
默认启动即实例化 所有单例 Bean(预实例化);需要懒加载可在 Bean/配置类/启动类上标 @Lazy,或全局配置 spring.main.lazy-initialization=true(一般不全局开,会把问题推迟到运行期)。