Spring Boot 3.x + 微服务速查手册(2026 面试版)
最后更新:2026-08-10
本手册面向 Java 高级开发工程师面试,覆盖 Spring Boot 3.x 核心特性、微服务架构设计与治理实战。 风格:说人话、给话术、上案例,不搞照本宣科。
目录
1. Spring Boot 3.x 核心变化
1.1 一句话概括
Spring Boot 3.x = JDK 17 起步 + Jakarta EE 全面替换 + 云原生优先(Native Image) + 可观测性内置。
1.2 关键变化一览
| 变化点 | Spring Boot 2.x | Spring Boot 3.x | 面试要点 |
|---|---|---|---|
| JDK 最低版本 | JDK 8 | JDK 17(推荐 JDK 21) | 虚拟线程(Virtual Thread)JDK 21 才支持 |
| Java EE 包名 | javax.* | jakarta.* | 不是简单换包名,涉及大量第三方库适配 |
| Native Image | 不支持 | 支持 GraalVM Native Image | 启动时间从秒级到毫秒级,内存省 70%+ |
| AOT 编译 | 无 | 有 AOT Processing | 编译期生成 BeanDefinition,减少反射开销 |
| 可观测性 | 需要自己集成 | Micrometer Observation API 内置 | 统一 Metrics + Tracing + Logging |
| Security | WebSecurityConfigurerAdapter | 基于组件式 SecurityFilterChain | 老写法直接删了,新写法用 Bean 注入 |
| 自动装配注册 | spring.factories | AutoConfiguration.imports | 3.x 两种方式都兼容,但推荐新方式 |
| HTTP Client | RestTemplate 为主 | 推荐 RestClient / HTTP Interface Client | RestClient 是 3.2 新增的流式 API |
1.3 JDK 21 虚拟线程实战
面试怎么说:「Spring Boot 3.2 开始支持虚拟线程,我们项目从 JDK 17 升到了 21,开启虚拟线程后,Tomcat 线程池从 200 缩减到 50,但并发能力提升了一倍多。核心原因是虚拟线程在 IO 阻塞时会自动让出载体线程,特别适合我们这种 IO 密集型的微服务场景。」
1.4 Jakarta EE 迁移踩坑
真实踩坑场景:
用了老版本 MyBatis-Plus(3.5.x 以下),启动直接报
ClassNotFoundException: javax.servlet.FilterSwagger(SpringFox)不兼容了,要换成 SpringDoc(
springdoc-openapi-starter-webmvc-ui)@Validated从javax.validation变成jakarta.validation
迁移口诀:javax 换 jakarta,插件帮你批量改,SpringFox 换 SpringDoc,Hibernate Validator 升 8.x
1.5 Native Image 实战数据
| 指标 | JVM 模式 | Native Image |
|---|---|---|
| 启动时间 | 2.3s | 0.08s |
| 内存占用 | 320MB | 85MB |
| 打包时间 | - | 约 3-5 分钟 |
| 反射支持 | 完整 | 需要手动注册(reflect-config.json) |
面试怎么说:「我们有两个服务做了 Native Image,一个是网关,一个是 BFF 层。网关启动从 8 秒降到 80 毫秒,在 K8s 里弹性扩缩容速度非常快。但要注意,Native Image 不支持动态类加载,像 CGLIB 动态代理这类需要编译期处理,所以不是所有服务都适合做 Native。」
2. 自动装配原理
2.1 一句话原理
自动装配 = 条件装配 + SPI 机制 + 约定大于配置。 Spring Boot 启动时扫描所有 jar 包里的自动配置类,按条件判断要不要生效。
2.2 装配链路(3.x 新版)
2.x vs 3.x 区别:
| 2.x | 3.x | |
|---|---|---|
| 配置文件 | META-INF/spring.factories | META-INF/spring/...AutoConfiguration.imports |
| 格式 | key=value(EnableAutoConfiguration=类名) | 每行一个类名,简单直接 |
| 向后兼容 | - | 3.x 仍然兼容 spring.factories,但推荐新方式 |
2.3 核心条件注解速查
| 注解 | 含义 | 使用场景 |
|---|---|---|
@ConditionalOnClass | classpath 下有某个类才生效 | 引入了某个 starter 才生效 |
@ConditionalOnMissingBean | 容器里没有某个 Bean 才创建 | 用户没自定义就用默认的 |
@ConditionalOnProperty | 配置文件满足某个属性 | 开关控制 |
@ConditionalOnWebApplication | 是 Web 应用才生效 | Web 专属配置 |
@ConditionalOnMissingClass | classpath 下没有某个类 | 和 OnClass 配合做互斥 |
2.4 自定义 Starter 完整流程
场景:公司要统一日志格式(加 traceId、env、app_name),做一个 company-log-spring-boot-starter。
核心代码:
imports 文件内容:
面试怎么说:「我们做了 20+ 个内部 starter,比如统一鉴权、统一日志、分布式 ID、灰度路由。套路都一样:一个 Properties 类管配置,一个 AutoConfiguration 类管装配,条件注解控制生效时机。关键是
@ConditionalOnMissingBean,这样业务方如果有定制需求,自己定义一个 Bean 就能覆盖默认实现。」
3. Spring Boot 启动流程
3.1 SpringApplication.run() 核心流程
3.2 关键扩展点
| 扩展点 | 时机 | 典型用途 |
|---|---|---|
ApplicationContextInitializer | 容器 refresh 之前 | 加环境变量、改配置源 |
ApplicationListener | 各阶段事件监听 | 启动耗时统计、预热缓存 |
ApplicationRunner / CommandLineRunner | 容器完全启动后 | 数据初始化、任务调度启动 |
ApplicationStartup | 启动过程埋点 | Spring Startup Actuator 查看启动耗时 |
3.3 Bean 生命周期(简化版 — 面试够用了)
口诀:实例化 → 注入 → Aware → Before → 初始化 → After → 使用 → 销毁
3.4 循环依赖
经典三级缓存(Spring 6 / Boot 3 之前):
| 缓存 | 作用 |
|---|---|
singletonObjects(一级) | 完整 Bean |
earlySingletonObjects(二级) | 早期暴露的 Bean(可能还没属性填充) |
singletonFactories(三级) | Bean 的 ObjectFactory(用于创建代理对象) |
Spring Boot 2.6+ / 3.x 变化:
默认禁止循环依赖!启动直接报错。
需要手动开启:
spring.main.allow-circular-references=true(生产环境不推荐)正确做法:重构代码,用
@Lazy或提取公共 Bean 来打破循环
面试怎么说:「Spring Boot 3.x 默认不允许循环依赖,这是一个设计信号——循环依赖说明你的模块划分有问题。我们项目里遇到循环依赖,一般两种解法:一是用
@Lazy延迟注入;二是重构,把互相依赖的逻辑抽到一个中间服务里。如果是构造器注入的循环依赖,那只能用@Lazy或者改成 setter 注入了。」
4. 微服务架构设计
4.1 服务拆分原则
一句话:按业务边界拆,不按技术层拆。
DDD 战略设计四步法:
事件风暴:梳理业务领域事件
统一语言:和产品对齐术语(不要一个东西三个名)
限界上下文:划定服务边界
上下文映射:定义服务间关系(防腐层、开放主机服务等)
拆分反模式:
| 反模式 | 问题 | 正确做法 |
|---|---|---|
| 按技术层拆(User-API、User-Service、User-DAO) | 一个需求改三个服务 | 按业务领域拆 |
| 拆太细(一个 CRUD 一个服务) | 运维成本爆炸 | 合理聚合 |
| 共享数据库 | 改表全链路崩溃 | 每个服务独立数据库 |
4.2 服务间通信方式对比
| 方式 | 协议 | 性能 | 适用场景 | 典型技术 |
|---|---|---|---|---|
| REST/HTTP | HTTP/1.1 或 2 | 中等 | 对外 API、简单调用 | Spring WebFlux / RestClient |
| gRPC | HTTP/2 + Protobuf | 极高 | 内部高频调用、流式传输 | grpc-spring-boot-starter |
| 消息队列 | TCP | 异步解耦 | 削峰、最终一致性、事件驱动 | RocketMQ Kafka Pulsar |
| GraphQL | HTTP | 中等 | BFF 层、前端灵活查询 | spring-graphql |
选型口诀:同步低延迟选 gRPC,简单好调试选 REST,异步解耦选 MQ,前端灵活查选 GraphQL
4.3 API 网关设计(Spring Cloud Gateway)
核心功能:
路由转发
鉴权(JWT 校验)
限流(RequestRateLimiter + Redis)
灰度发布(权重路由)
日志 & 链路追踪
网关设计要点:
网关不处理业务逻辑,只做路由和横切关注点
鉴权放网关,但细粒度权限放各服务
网关要做限流,不然一波流量直接把后端打挂
网关本身要无状态,方便水平扩展
4.4 服务注册发现(Nacos)
Nacos vs Eureka vs Consul:
| 特性 | Nacos | Eureka | Consul |
|---|---|---|---|
| 健康检查 | TCP/HTTP/MySQL/自定义 | 心跳 | TCP/HTTP/gRPC |
| 配置中心 | 内置 | 不支持 | 支持 |
| 负载均衡 | 权重 | 区域 | 多策略 |
| 跨数据中心 | 支持 | 不支持 | 支持 |
| CAP 模型 | AP + CP 可切换 | AP | CP |
面试怎么说:「我们用 Nacos 做注册中心 + 配置中心,一个组件解决两个问题。Nacos 支持 AP 和 CP 模式切换——临时实例走 AP(适合大部分微服务),持久化实例走 CP(适合 DNS/网关路由这种不能丢的)。而且 Nacos 的权重路由功能,在灰度发布时非常有用。」
4.5 配置中心(Nacos Config)
配置优先级(从高到低):
Nacos 指定 profile 配置(
app-dev.yaml)Nacos 默认配置(
app.yaml)本地
application-{profile}.yaml本地
application.yaml
动态刷新:
4.6 链路追踪(Micrometer + OpenTelemetry)
Spring Boot 3.x 用 Micrometer Tracing 替代了之前的 Spring Cloud Sleuth。
面试怎么说:「我们链路追踪用的是 OpenTelemetry + Jaeger,Spring Boot 3.x 原生支持 Micrometer Tracing,只需要引入
micrometer-tracing-bridge-otel和opentelemetry-exporter-otlp两个依赖,配置一下 endpoint 就行了。traceId 会自动在日志里打印,排查问题的时候 grep 一下就能把整条链路串起来。」
5. 服务治理实战
5.1 限流:Sentinel 实战
四种流控效果:
| 效果 | 说明 | 场景 |
|---|---|---|
| Quick Fail(快速失败) | 超过阈值直接拒绝 | 最常用,简单粗暴 |
| Warm Up(预热) | 慢慢增加通过的 QPS | 防止冷启动流量冲击 |
| Rate Limiter(匀速排队) | 漏桶算法,匀速处理 | 保护下游慢服务 |
| Warm Up + 排队 | 预热 + 排队 | 大促开场 |
5.2 熔断降级
Sentinel 熔断策略:
| 策略 | 触发条件 | 说明 |
|---|---|---|
| 慢调用比例 | 响应时间 > 阈值的请求比例过高 | 适合保护慢下游 |
| 异常比例 | 异常请求比例过高 | 适合下游不稳定场景 |
| 异常数 | 异常数超过阈值 | 简单粗暴 |
实战建议:
慢调用阈值设为正常 RT 的 2-3 倍
熔断时间先设 10s,观察调整后固定
Fallback 不要返回 null,返回缓存数据或默认值
核心链路和非核心链路分开降级
5.3 负载均衡策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| RoundRobin | 轮询 | 服务实例配置相同 |
| Random | 随机 | 简单场景 |
| Weighted | 权重 | 灰度发布、机器配置不同 |
| LeastActive | 最少活跃调用数 | 服务处理能力差异大 |
| ConsistentHash | 一致性哈希 | 有缓存场景(相同请求到同一实例) |
5.4 重试机制设计
原则:
只对 读操作 或 幂等写操作 重试
有 最大重试次数 和 退避策略
重试要带 超时,防止雪崩
5.5 幂等性保证方案
| 方案 | 原理 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| Token 机制 | 先获取 token,提交时携带,用完即焚 | 表单提交、支付 | 简单可靠 | 多一次网络请求 |
| 数据库唯一键 | INSERT 时用唯一索引防重复 | 创建订单 | 最简单 | 只能防数据库层面 |
| Redis SETNX | 用请求 ID 做 key,设过期时间 | 通用场景 | 性能好 | Redis 挂了要兜底 |
| 状态机 | 状态只能单向流转 | 订单、审批 | 业务层面保证 | 要设计好状态图 |
面试怎么说:「支付回调幂等我们用了两层保证:第一层 Redis SETNX,key 是
pay_notify:{tradeNo},5 分钟过期;第二层数据库唯一索引uk_trade_no。Redis 成功了就直接返回,Redis 挂了还有数据库兜底。状态机方面,订单状态只能单向流转(待支付 - 已支付 - 已发货),反向操作直接拒绝。」
6. 分布式事务
6.1 方案对比
| 方案 | 一致性 | 性能 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| 2PC(强一致) | 强一致 | 低(锁资源时间长) | 高 | 银行转账、金融核心 |
| TCC | 最终一致 | 中 | 极高(要写三个接口) | 资金、库存等核心场景 |
| SAGA | 最终一致 | 高 | 中 | 长事务、跨多个服务 |
| 本地消息表 | 最终一致 | 高 | 中 | 异步解耦、对实时性要求不高 |
| 消息事务(RocketMQ) | 最终一致 | 高 | 低 | 订单 + 库存 + 积分这类 |
| Seata AT | 最终一致 | 中 | 低(框架帮你做) | 中小项目、快速落地 |
6.2 Seata AT 模式原理
优点:业务无侵入(只需加 @GlobalTransactional 注解)
缺点:依赖全局锁,高并发下性能有瓶颈
6.3 实战选型指南
面试怎么说:「我们电商项目的下单流程用的是 RocketMQ 事务消息。下单时先发半消息,然后执行本地订单创建,成功后提交消息,库存服务和积分服务消费消息做各自的事情。如果本地事务失败了,半消息回滚,下游不会收到消息。这种方式吞吐量高,而且下游服务可以独立重试。对于支付这种强一致性要求高的场景,用的是 TCC 模式。」
7. 微服务监控与运维
7.1 监控四根支柱
| 支柱 | 工具 | 关注什么 |
|---|---|---|
| 健康检查 | Spring Actuator | 服务活着没 |
| 日志 | ELK / Loki + Grafana | 发生了什么 |
| 指标 | Prometheus + Grafana | 性能怎么样 |
| 链路 | OpenTelemetry + Jaeger/Tempo | 请求去了哪里 |
7.2 健康检查(Actuator)
自定义健康指标:
7.3 日志收集
推荐架构:应用日志 → Filebeat/Fluentd → Kafka → Elasticsearch/Loki → Grafana
日志规范:
必须包含
traceId、spanIdJSON 格式(方便 ELK 解析)
敏感信息脱敏
不同级别分文件(INFO WARN ERROR)
7.4 指标监控
关键指标:
| 类别 | 指标 | 告警阈值(参考) |
|---|---|---|
| JVM | 堆内存使用率 | > 80% |
| JVM | GC 频率 | Full GC > 1次/小时 |
| HTTP | P99 延迟 | > 500ms |
| HTTP | 5xx 错误率 | > 1% |
| 系统 | CPU 使用率 | > 70% |
| 线程池 | 队列堆积量 | > 80% |
| 连接池 | 活跃连接数 | > 80% 最大连接数 |
7.5 告警方案设计
面试怎么说:「我们监控体系是 Prometheus + Grafana + AlertManager。Prometheus 负责采集指标,Grafana 做可视化大盘,AlertManager 负责告警路由。告警分级管理,P0 级走电话 + 钉钉群,P1 级钉钉通知,P2/P3 级邮件。关键是要有告警收敛,不然一波告警风暴根本看不过来。」
8. Spring Boot 3.x + AI 集成
8.1 Spring AI 框架概述
Spring AI 是 Spring 官方的 AI 集成框架(2023 年底开始,2024-2025 快速迭代),目标是让 AI 集成像 Spring 集成数据库一样简单。
核心抽象:
| 接口 | 作用 | 类比 |
|---|---|---|
ChatClient | 调用大模型对话 | 像 RestTemplate |
ChatModel | 模型实现(OpenAI/Ollama/通义等) | 像 DataSource |
EmbeddingModel | 文本向量化 | 用于 RAG |
VectorStore | 向量存储 | Redis/PG/Milvus |
FunctionCallback | Function Calling | 让模型调用你的代码 |
8.2 集成 OpenAI / 本地模型
8.3 RAG 模式实现
RAG = 检索增强生成,让大模型基于你的私有数据回答问题。
8.4 Function Calling
让大模型能调用你的业务方法。
面试怎么说:「我们在内部知识问答系统里用了 Spring AI + RAG。文档先做切分(500 token 一个 chunk),用 BGE 模型做 embedding,存在 Milvus 里。用户提问时检索 Top 5 相关片段,拼成 prompt 发给大模型。效果比纯模型回答准确率提升了 40%。另外 Function Calling 用在了智能客服里,模型可以调用订单查询、物流查询这些函数,用户说'我的快递到哪了',模型自动调用物流查询接口。」
9. 面试高频问答
Q1:Spring Boot 和 Spring 有什么区别?
回答:「Spring 是框架,Spring Boot 是脚手架。Spring 需要大量 XML 配置,Boot 用约定大于配置,内嵌 Tomcat,开箱即用。Spring Boot 不是替代 Spring,是让你更快用 Spring。」
Q2:@SpringBootApplication 包含了什么?
回答:「三个注解的组合:
@SpringBootConfiguration(本质是 @Configuration)、@EnableAutoConfiguration(开启自动装配)、@ComponentScan(组件扫描)。其中@EnableAutoConfiguration是核心,它通过 ImportSelector 读取 SPI 配置加载所有自动配置类。」
Q3:Spring Boot 配置文件加载优先级?
回答:「命令行参数 > 系统环境变量 > application-{profile}.yaml > application.yaml > @PropertySource 注解。实际生产中,我们用 Nacos 配置中心覆盖本地配置,优先级:Nacos 指定 profile > Nacos 默认 > 本地 profile > 本地默认。」
Q4:如何实现 Spring Boot 项目的热部署?
回答:「开发环境用 spring-boot-devtools,改完代码自动重启。生产环境不存在热部署,都是 CI/CD + 滚动更新。JRebel 也行但收费。」
Q5:Spring Boot 如何处理异常?
回答:「统一异常处理:
@RestControllerAdvice+@ExceptionHandler。全局捕获异常,返回统一格式{code, message, data}。关键异常要记日志,业务异常不记 error(记 warn),系统异常记 error + 告警。」
Q6:Spring Boot 如何实现异步?
回答:「
@Async+@EnableAsync。但要注意:1)@Async 方法必须在另一个 Bean 里(不能同类调用,因为是 AOP 代理);2)自定义线程池(默认的 SimpleAsyncTaskExecutor 每次都创建新线程);3)要有异常处理(实现 AsyncUncaughtExceptionHandler)。」
Q7:Spring Boot Starter 的原理?
回答:「Starter 就是一组依赖 + 自动配置。比如
spring-boot-starter-web引入了 Spring MVC + 内嵌 Tomcat + Jackson,同时通过AutoConfiguration.imports注册WebMvcAutoConfiguration。自定义 Starter 核心是写一个自动配置类,用条件注解控制生效时机。」
Q8:微服务之间如何传递用户信息?
回答:「网关鉴权后把 userId 放到请求头,通过 Feign/RestTemplate 的拦截器透传。也可以用
ThreadLocal在单服务内传递。注意:跨线程(如 @Async、线程池)时要手动传递 ThreadLocal,或者用InheritableThreadLocal。更好的方案是用 Micrometer 的 Context Propagation。」
Q9:如何做接口幂等?
回答:「看场景。创建类接口用唯一索引或 Token 机制;更新类接口用乐观锁(version 字段);支付回调用 Redis SETNX + 状态机。关键是幂等键的设计——不能只用请求参数,最好加上时间窗口。」
Q10:微服务如何做灰度发布?
回答:「Nacos 支持实例权重 + 元数据。网关根据请求头或用户 ID 路由到灰度实例。具体:灰度实例打
metadata.version=v2,网关配置路由规则,userId % 100 < 5的用户路由到 v2 版本。配合链路追踪标记灰度流量,方便监控灰度效果。」
Q11:Spring Boot 3.x 和 2.x 最大的区别是什么?
回答:「四个:1)JDK 最低 17,推荐 21(支持虚拟线程);2)javax 换 jakarta,影响大量第三方库;3)Native Image 支持,启动从秒级到毫秒级;4)Observability 内置,不用自己集成 Sleuth/Brave 了。」
Q12:什么是 AOT 编译?有什么好处?
回答:「AOT(Ahead of Time)是在编译期而不是运行期处理 Bean。Spring Boot 3.x 在编译时生成 BeanDefinition,减少运行期反射和动态代理。好处:启动快、内存省、Native Image 友好。缺点:不支持运行时动态生成 Bean。」
Q13:微服务如何做分布式配置?
回答:「我们用 Nacos Config。配置分环境、分版本,支持动态刷新(@RefreshScope)。配置变更实时推送到各服务,不用重启。关键配置变更要走审批流,有回滚能力。」
Q14:微服务如何做限流?
回答:「两层限流:1)网关层——Spring Cloud Gateway + Redis 令牌桶,防整体流量过大;2)服务层——Sentinel,按接口粒度控制。Sentinel 支持 QPS 限流、线程数限流、慢调用比例熔断。大促前要做全链路压测,确定限流阈值。」
Q15:分布式事务了解哪些方案?
回答:「2PC、TCC、SAGA、本地消息表、RocketMQ 事务消息、Seata AT。实际选型看场景:金融核心用 TCC,高并发异步场景用消息队列,快速落地用 Seata AT。我们电商项目用的是 RocketMQ 事务消息 + 本地消息表组合。」
Q16:如何保证微服务的可用性?
回答:「多层保障:1)多实例 + 负载均衡;2)熔断降级(Sentinel);3)超时 + 重试(指数退避);4)限流保护;5)健康检查 + 自动重启(K8s liveness probe);6)异地多活(核心场景)。」
Q17:Spring Boot 内嵌 Tomcat 的优缺点?
回答:「优点:开箱即用,部署简单,和 Spring 深度集成。缺点:性能调优空间有限,不适合超高并发场景。高并发我们用 Undertow 替换 Tomcat(性能更好),或者直接在前面加 Nginx 做反向代理。Spring Boot 3.x 还支持虚拟线程,Tomcat 线程池可以大幅缩小。」
Q18:如何做微服务的日志追踪?
回答:「全链路 traceId:1)网关生成 traceId,放到请求头;2)MDC(Mapped Diagnostic Context)把 traceId 注入到日志上下文;3)日志格式统一包含 traceId、spanId;4)日志收集到 ELK,按 traceId 检索。Spring Boot 3.x 用 Micrometer Tracing,自动传递 traceId。」
Q19:微服务如何做服务降级?
回答:「分核心和非核心。核心链路降级返回缓存数据或默认值,非核心链路直接熔断不返回。Sentinel 做熔断降级,配置慢调用比例或异常比例阈值,触发后走 Fallback 逻辑。关键是 Fallback 不能返回 null,要有兜底数据。」
Q20:你怎么理解 Spring Boot 的"约定大于配置"?
回答:「核心思想是:80% 的场景用默认配置就够了,只有 20% 的特殊场景才需要改配置。比如:引入 web starter 就自动有 Tomcat + Spring MVC;引入 DataSource 就自动配置连接池;端口默认 8080,不需要指定。这是通过自动配置类 + 条件注解实现的——默认提供一套实现,用户自定义 Bean 覆盖默认。」
附录:速查口诀
自动装配口诀
启动流程口诀
Bean 生命周期口诀
分布式事务选型口诀
使用说明:本手册适合面试前快速复习,建议配合实际项目经验理解每个知识点。面试时不要背答案,要结合自己的项目讲。
本内容由 Coze AI 生成,请遵循相关法律法规及《人工智能生成合成内容标识办法》使用与传播。