《Spring Boot 高级》目录
这一页是全书的入口。它不只列出 33 节的标题,还给出三条可以照着走的阅读路径、每一节的一句话说明,以及一张按排查场景索引的常见问题速查表。如果你不确定从哪开始,先读「本书定位」与「读者画像」;如果你已经带着一个具体问题来,直接跳到「常见问题速查」或「分部分章节」按编号定位。
全书结构是:正文 11 章 33 节 + 目录 1 篇,共 34 篇。正文按「从容器内部到交付运行」的顺序分为四个部分:先拆开容器与装配机制,再看 Web 请求怎么被处理,接着进入数据、事务与安全,最后落到构建产物、可观测性与版本迁移。
如何使用本目录
这一页有三种用法,取决于你此刻的状态。
如果你准备系统读一遍,按顺序读「本书定位」「读者画像」「学习路径」三节,用十分钟决定自己的入口。高级卷与实战卷的差别在于:实战卷回答「这么配能跑、为什么这么选」,本卷回答「框架内部是怎么实现的」。如果你还没独立交付过一个服务,建议先读实战卷——本卷的很多结论要落在具体工程决策上才有意义。
如果你已经带着问题来,直接看「常见问题速查」。它按排查场景组织,每条给出简短回答与对应章节,定位到章节后再顺着那节的「小结」补齐背景,通常比通读整章更快。
如果你在核对某个具体机制,用「分部分章节」的表格按编号定位。每一行都有一句话说明,写清那一节讲什么、回答哪个问题,可以帮你确认是不是要找的那一节。
三种用法之外还有一种:把这一页当索引页长期放在收藏夹里。本卷 33 节分布在 11 章中,章节编号即定位坐标,表格里的每一行都可以直接点进去。当你已经读过一遍、只需要偶尔回查某个机制时,用这一页跳转通常比用站点搜索更快。
本书定位
这是一本面向已经能独立交付服务、想理解框架内部机制的工程师的书。它不教你怎么写一个 Controller,也不教你怎么配连接池——那些在入门卷与实战卷里已经讲过。它回答的是更靠里的一层问题:SpringApplication.run() 之后容器按什么顺序做了什么、自动配置类是怎么被挑出来的、一个 @Transactional 方法在字节码层面被织进了什么、请求从进入容器到返回响应经过了哪些组件。
它有三个刻意的取舍。
第一,每条结论都尽量落到可核实的证据上。书中大量结论来自对 4.1.1 实际 jar 的反编译核实(javap、unzip)与官方源码,而不是「我记得是这样」。凡是无法在本机核实的部分——原生镜像的构建产物、Kubernetes 与可观测性后端的运行输出、async-profiler 的火焰图——正文一律显式标注为「示例输出」,并给出你自己验证的步骤。
第二,只讲那些能改变你做法的机制。框架内部细节无穷无尽,本卷不追求穷举。挑选标准是:知道之后能解释一个常见现象、能定位一类线上问题、或者能在两个方案之间做出有依据的选择。纯粹的实现细节会被略过,或者压缩成一句「这里不必展开」。
第三,把「为什么这样设计」与「知道之后能做什么」并列。每一节都尽量回答三个问题:框架内部怎么做、为什么这样设计、知道这件事之后你能做什么。只讲机制而不讲用途,读起来会变成背源码。
如果你需要的是一份「照着配就能跑」的参考手册,实战卷更合适;如果你希望下次遇到「这个注解为什么不生效」「这个 bean 为什么初始化了两次」时能自己定位到具体机制,那本卷的深度是合适的。
与入门卷、实战卷的关系
三部曲不是三个独立话题,而是同一条能力线上的三个高度。理解它们的边界,能帮你判断某个问题该去哪一卷找答案。
| 维度 | 入门卷 | 实战卷 | 本卷(高级) |
|---|---|---|---|
| 回答的问题 | 怎么用 | 怎么选、代价是什么 | 内部怎么实现 |
| 典型内容 | 注解语义、配置项、起步依赖 | 模块划分、缓存一致性、连接池调优、部署回滚 | refresh() 步骤、代理边界、事务同步、AOT 处理 |
| 读完能做什么 | 写出可运行的服务 | 交付可维护、可上线的服务 | 定位机制类问题、在方案之间做有依据的取舍 |
| 前置依赖 | 无 | 入门卷 | 入门卷 + 实战卷 |
三卷之间存在大量交叉引用,但每一卷都自成闭环:本卷不假设你记得实战卷里的某个具体配置,需要用到时会重新交代背景;实战卷也不假设你读过本卷,涉及内部机制时会给出「详见高级卷某节」的指引。因此你不必按顺序读三卷,也可以直接进本卷。
判断一个问题属于哪一卷,标准很简单:答案会不会随框架版本变化。会变的属于用法——某个配置项叫什么、某个 starter 的坐标是什么、某个版本的默认值是多少——这些在入门卷与实战卷。不变的是机制——容器按什么顺序启动、代理在什么条件下失效、事务同步回调在哪个阶段触发——这些在本卷,而且换个框架版本仍然成立。
怎么自己核实书中的结论
本卷的结论密度比较高,光靠记忆容易混。正文里凡是可以核实的结论,都给了核实方法;下面把最常用的几种集中列一遍,方便你在读每一节时随手验一遍。
查类的真实包路径与结构:用 javap。Spring Boot 4.x 做了模块化拆分,很多类换了模块甚至换了包,凭 3.x 的记忆写 import 会直接编译失败。拿到 jar 之后 unzip -l 看有哪些类、javap -p -c 看方法与字节码,比查文档更可靠。
查配置属性的真实名称:解压 spring-boot-*-4.1.1.jar 里的 META-INF/spring-configuration-metadata.json,属性名、类型、默认值、废弃状态都在里面。文档与代码不一致时以元数据为准。
查自动配置清单:看 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里面列出的才是真正会被加载的自动配置类。很多「我写了自动配置类但没生效」的问题,根因就是没有出现在这个文件里。
查运行时实际装配了什么:用 --debug 或 logging.level.org.springframework.boot.autoconfigure=DEBUG 打印条件评估报告,能直接看到哪些配置类被应用、哪些被条件挡下、挡下它的条件是什么。
查请求处理链与过滤器链:Security 用 @EnableWebSecurity(debug=true) 打印实际的过滤器链顺序;MVC 用日志或断点看 HandlerMapping 与 HandlerAdapter 的选择结果。
这些手段的共同点是:不依赖记忆,也不依赖文档版本。本卷鼓励你在读每一节时都动手验一次,这既是确认书中结论的方式,也是把机制变成自己判断力的方式。
读者画像
不同类型的读者,起点和建议入口差别很大。先在下面找到最接近自己的那一类。
① 读过入门卷与实战卷、想补齐原理的工程师。这是本卷的目标读者。建议从第 1 章顺序读到第 11 章。第一部分(第 1–3 章,容器内部机制)是全书的地基,后面每一章都会用到它;第二部分(第 4–5 章)与第三部分(第 6–8 章)是主体;第四部分(第 9–11 章)按需取舍。
② 正在排查一个具体问题的工程师。你不需要按顺序读。代理失效、循环依赖、@Transactional 不回滚、连接被提前占用、过滤器顺序不对——这些在「常见问题速查」里都有入口,定位到章节后读那一节即可。这类读者通常收获最直接,因为问题本身就是理解机制的最好切口。
③ 准备做 3.x → 4.x 迁移的工程师。建议先读第 11 章(迁移线集中在这里),再回头补第 1–2 章的容器与自动配置机制——4.x 的模块化重构会直接改变你写 import 与声明依赖的方式,不理解机制就只能照抄迁移清单。
④ 想理解响应式与虚拟线程这类新范式的开发者。直接读第 5 章(WebFlux 与 Reactor)与第 7.2 节(虚拟线程)。这两处是 4.x 与 3.x 差别最明显、也最容易凭印象写错的地方,书中对每条结论都标注了版本边界与核实方式。
学习路径
下表给出三条典型路径。三条路径不互斥,可以先跳读救急,再回头补齐。
| 路径 | 适合谁 | 读哪些 | 预计用时 |
|---|---|---|---|
| 完整通读 | 读过前两卷、想系统补齐原理 | 第 1 章至第 11 章顺序读,每节配合 jar 核实 | 7–9 周(每天 1 小时) |
| 按问题跳读 | 手上正有具体问题待排查 | 按「常见问题速查」入口选:3.3、1.3、7.3、6.3、8.1、2.3 等 | 2–3 周 |
| 迁移优先 | 准备 3.x → 4.x 迁移 | 11.1 → 11.2 → 11.3,再补 1.1、2.1 | 1–2 周 |
按问题跳读这条路径的入口不是章节顺序,而是你此刻遇到的现象:注解不生效看 3.3,循环依赖报错看 1.3,线程池被撑爆看 7.3,连接在方法一开始就被占用看 6.3,过滤器顺序不对看 8.1,自定义自动配置没生效看 2.3。每一节都自成闭环,但都会引用相关章节,读完后可以顺着引用补齐。
一份可执行的八周计划
上面三条路径偏原则。如果你希望有一份可以直接照着打勾的安排,下面这份八周计划可以作为起点(按每天投入一小时估算),它对应的是「完整通读」路径。
| 周次 | 主要任务 | 完成标志 |
|---|---|---|
| 第 1 周 | 第 1 章:启动流程、Bean 定义、依赖解析与循环依赖 | 能画出 refresh() 的主要步骤并说出断点位置 |
| 第 2 周 | 第 2–3 章:自动配置与条件装配、AOP 与代理 | 能解释自定义自动配置为什么没生效、注解为什么被绕过 |
| 第 3 周 | 第 4 章:MVC 处理链、参数解析与消息转换、异常解析 | 能说清一次请求经过哪些组件、异常被谁接住 |
| 第 4 周 | 第 5 章:Reactor 与背压、WebFlux 处理、阻塞隔离 | 能判断一段代码该不该放进 boundedElastic |
| 第 5 周 | 第 6 章:持久化上下文、Flush 时机、连接与延迟加载 | 能解释连接何时被占用、延迟加载为何抛异常 |
| 第 6 周 | 第 7 章:事务同步与事件、虚拟线程、线程池模型 | 能说清事务提交后发消息该怎么写、pinning 何时发生 |
| 第 7 周 | 第 8 章:过滤器链、认证授权流程、方法安全与传播 | 能读懂 debug 模式的过滤器链并定位越权问题 |
| 第 8 周 | 第 9–11 章:AOT 与原生镜像、可观测性机制、迁移 | 能判断服务适不适合上原生镜像、能列出迁移步骤 |
这份计划的关键不在于准时,而在于每一周都有一处可以动手核实的机制。高级卷的内容光读记不住,配合 javap、unzip、--debug、JFR 这些手段自己验一遍,印象才会留下来。
版本与示例约定
本卷所有结论以 Spring Boot 4.1.1 + Java 21(Temurin 21.0.12.1) 为基线,构建工具为 Maven 3.9.12,对照线为 Spring Boot 3.5.16。凡 3.5.x 与 4.1.x 行为不同之处,正文会两版分别标注;凡涉及版本边界(例如虚拟线程的 pinning 行为在 JDK 21 与 JDK 24 不同)也会显式说明。
本机没有的东西:GraalVM 的 native-image、Kubernetes 集群、Prometheus / Jaeger / Zipkin 后端、async-profiler。涉及这些工具或后端的构建日志、运行输出、界面截图、火焰图,正文一律标注为「示例输出」,并给出你在自己环境里复现的步骤。只有纯 Spring Boot 应用的启动、构建,以及 JDK 自带的 jcmd / jfr / jstack 输出,才引用本机实测数据。
性能相关的数字只给量级与测量方法,不给出未经实测的精确值。要数字的地方,正文给的是「怎么测出这个数字」的步骤,而不是一个拍脑袋的结果。
四个部分之间的依赖关系
正文按「从容器内部到交付运行」的顺序分为四个部分,它们之间是递进关系:
| 部分 | 章节 | 回答什么问题 | 依赖谁 |
|---|---|---|---|
| 第一部分 容器内部机制 | 第 1–3 章 | 容器怎么启动、Bean 从哪来、注解怎么被织进去 | 无 |
| 第二部分 Web 请求处理 | 第 4–5 章 | 一次请求经过哪些组件、响应式栈有何不同 | 第一部分 |
| 第三部分 数据、事务与安全 | 第 6–8 章 | 持久化上下文与连接怎么流转、鉴权在哪个环节生效 | 第一部分、第二部分 |
| 第四部分 构建、可观测与迁移 | 第 9–11 章 | 构建期做了什么、运行期怎么看、怎么从 3.x 迁过来 | 前三部分全部 |
第一部分是全书的地基,不能跳。第 1–3 章讲的是容器启动、自动配置装配与代理机制,后面每一章都会用到。尤其是第 3 章的代理机制——不理解它,@Transactional 失效、@Async 不生效、@Cacheable 没起作用这些现象都只能靠记结论。
第二部分与第三部分是主体。Web 请求处理(第 4–5 章)覆盖 MVC 管线与响应式栈;数据、事务与安全(第 6–8 章)覆盖持久化上下文、事务同步、虚拟线程、过滤器链与授权。这两部分合计 5 章 15 节,是最接近日常排查场景的内容。
第四部分按需取舍。第 9 章(AOT 与原生镜像)如果你不上原生镜像可以快读;第 10 章(可观测性机制)建议至少读完 10.1 与 10.3;第 11 章(迁移)如果你还在 3.x 上,则应当优先读。
可以跳读的是部分章节。第 5 章(WebFlux)如果你不做响应式可以跳过;第 9.2、9.3 如果不碰原生镜像可以只读 9.1 了解 AOT 处理;但第 1–3 章、第 6 章、第 7.1 与 7.3 属于几乎所有服务都会碰到的内容,建议不要跳过。
分部分章节
下面按部分列出全部 33 节。每一行都有一句话说明,写清那一节回答什么问题,用来帮你确认这是不是你要找的那一节。
第一部分:容器内部机制(第 1–3 章)
这一部分拆开 Spring 容器的三个核心机制:启动流程、自动配置装配、代理。读完能解释大部分「明明配了却不生效」的现象。
| 编号 | 章节 | 说明 |
|---|---|---|
| 1.1 | ApplicationContext 启动流程 | 从 SpringApplication.run() 追到容器可用,拆开 refresh() 的各个步骤,标出两类后处理器的介入时机与断点位置 |
| 1.2 | Bean 定义注册与合并 | 讲清 BeanDefinition 的结构、组件扫描如何产出定义、父子定义的合并规则,以及同名定义冲突时谁赢 |
| 1.3 | 依赖解析与循环依赖 | 走一遍 getBean() 的解析流程,解释三级缓存为什么能解掉 setter 循环依赖、构造器注入为什么必然失败 |
| 2.1 | 自动配置类的加载顺序 | 4.x 的 imports 文件里有多少条、@AutoConfiguration 的语义,以及排序靠什么决定、为什么要有字典序兜底 |
| 2.2 | @Conditional 家族实现 | 条件是在哪个阶段被评估的、OnClassCondition 这类实现怎么工作,以及评估结果如何进 --debug 报告 |
| 2.3 | 自动配置的覆盖与排除 | 自动配置如何为用户定义「让路」、两种排除方式的差别,以及覆盖自动配置 Bean 的几种做法与风险 |
| 3.1 | JDK 动态代理与 CGLIB | 两种代理的选择规则到底是什么、proxyTargetClass 如何改变结果,以及 CGLIB 内联进 spring-core 后的影响 |
| 3.2 | 切面织入与顺序 | @Aspect 如何变成 Advisor、多个 advice 如何串成调用链,以及 @Order 与同切面内 advice 的相对次序 |
| 3.3 | 代理失效的边界 | 自调用、private / final / static 方法为什么绕过代理,以及 AopContext.currentProxy() 与自注入两种解法的代价 |
第二部分:Web 请求处理(第 4–5 章)
这一部分处理「一次请求进来之后发生了什么」,并对照讲清响应式栈与阻塞栈的根本差异。
| 编号 | 章节 | 说明 |
|---|---|---|
| 4.1 | DispatcherServlet 处理链 | 逐段拆开 doDispatch(),讲清 HandlerMapping 如何找到 handler、HandlerAdapter 这一层为什么存在 |
| 4.2 | 参数解析与消息转换 | 参数解析器的默认顺序、@RequestBody 如何按 Content-Type 选中消息转换器,以及自定义的注册位置 |
| 4.3 | 过滤器、拦截器与异常解析 | Filter 与 Interceptor 的执行时机差异、异常解析链的固定顺序,以及 @ResponseStatus 在哪一环被处理 |
| 5.1 | 响应式类型与背压 | Mono / Flux 的语义与惰性、Reactive Streams 的 request(n) 协议如何构成背压,以及各种背压策略的适用场景 |
| 5.2 | WebFlux 请求处理 | WebFlux 与 MVC 是两条独立栈、DispatcherHandler 与 WebFilter 的职责,以及函数式端点与注解式端点的取舍 |
| 5.3 | 阻塞代码的隔离 | 在事件循环线程上跑阻塞代码会发生什么、publishOn 与 subscribeOn 的差别,以及如何用 BlockHound 把问题抓出来 |
第三部分:数据、事务与安全(第 6–8 章)
这一部分覆盖最容易出线上问题的三块:持久化上下文与连接、事务与线程模型、认证与授权。
| 编号 | 章节 | 说明 |
|---|---|---|
| 6.1 | EntityManager 与持久化上下文 | 注入的 EntityManager 为什么是个代理、实体的四种状态如何转换,以及持久化上下文何时创建与销毁 |
| 6.2 | 事务与 Flush 时机 | Hibernate 在哪些时刻 flush、FlushMode 各取值的含义,以及 readOnly 在 ORM 层实际改变了什么 |
| 6.3 | 连接获取与延迟加载 | 一次事务里连接何时被占用与归还、LazyConnectionDataSourceProxy 的意义,以及 open-in-view 的代价 |
| 7.1 | 事务同步与事件 | TransactionSynchronizationManager 的机制、@TransactionalEventListener 四个 phase 的语义,以及提交后发消息为什么靠它 |
| 7.2 | 虚拟线程下的 Spring | 开启虚拟线程后框架替换了哪些组件、synchronized 导致的 pinning 在哪个 JDK 版本被修掉,以及它适合什么任务 |
| 7.3 | 并发编程与线程池模型 | ThreadPoolTaskExecutor 的队列策略、@Async 默认执行器为什么危险,以及上下文如何跨线程传递 |
| 8.1 | 过滤器链构建过程 | springSecurityFilterChain 是怎么被创建并注册的、HttpSecurity 的 DSL 装配出什么,以及多个链如何匹配 |
| 8.2 | 认证与授权流程 | ProviderManager 与认证提供者的协作、SecurityContext 的存储与保存策略,以及授权决策链怎么走 |
| 8.3 | 方法安全与上下文传播 | @EnableMethodSecurity 背后仍是 AOP、表达式求值拿到哪些上下文,以及安全上下文如何跨线程传播 |
第四部分:构建、可观测与迁移(第 9–11 章)
这一部分讲构建期与运行期各自发生了什么,最后落到 3.x → 4.x 的迁移。
| 编号 | 章节 | 说明 |
|---|---|---|
| 9.1 | AOT 处理与生成物 | AOT 处理在构建期做了什么、生成物有哪些、扩展点是什么,以及 AOT 模式下容器为什么能少走反射 |
| 9.2 | 反射与资源配置 | 反射与动态代理在原生镜像下为什么失败、RuntimeHints 如何声明元数据,以及排查配置缺失的手段 |
| 9.3 | 原生镜像的构建与权衡 | 原生镜像换来什么、付出什么代价、哪类服务适合上,以及它与 CDS 等手段的关系 |
| 10.1 | Micrometer 指标模型 | 四种计量器的语义差异、Observation 如何统一指标与追踪、MeterFilter 能做什么,以及 P99 怎么才算对 |
| 10.2 | 分布式追踪实现 | 追踪门面为什么这样设计、桥接实现的取舍、采样策略如何组合,以及传播格式的差别 |
| 10.3 | 生产问题诊断手段 | JFR 记录什么、jcmd 与线程转储怎么用、堆转储怎么获取与分析,以及在线诊断工具的风险 |
| 11.1 | Spring Boot 4 的模块化重构 | 大模块被拆成了什么、starter 改名对照,以及这对依赖声明与 import 语句的实际影响 |
| 11.2 | 依赖与配置迁移清单 | 按依赖关系排好序的迁移步骤:坐标与版本、类与注解改名、配置属性重命名,以及每一步怎么验证 |
| 11.3 | 迁移实测与回滚策略 | 迁移时如何分批验证、哪些改动不可回滚、怎么用特性开关降低风险,以及什么情况下不该迁 |
常见问题速查
下面这些是排查时最常碰到的现象,先在这里给出简短回答,详细机制展开在对应章节。回答只给方向,具体步骤请到对应章节查。
| 现象 | 简短回答 | 详见 |
|---|---|---|
同类里调自己的 @Transactional 方法,事务没生效? | 自调用绕过了代理,方法上的注解根本没被拦截到;改用自注入或 AopContext.currentProxy() | 3.3 |
| 启动时报循环依赖错误? | 构造器注入的循环依赖无法用三级缓存解决,只能靠重构、@Lazy 或 ObjectProvider 破环 | 1.3 |
| 自定义的自动配置类没生效? | 先看它有没有被 AutoConfiguration.imports 登记,再看条件是否满足、是否被用户定义「劝退」 | 2.3 |
@Async 方法同步执行了? | 同样是自调用绕过代理;另外要确认默认执行器是否被换成有界线程池 | 3.3、7.3 |
| 线程池队列无限增长最后 OOM? | ThreadPoolTaskExecutor 的队列容量默认无界,max-size 形同虚设,必须显式设 queue-capacity | 7.3 |
| 事务方法一开始连接就被占满了? | 显式隔离级别或 readOnly 会让事务开始时即取物理连接;默认设置下连接在首条 SQL 时才取 | 6.3 |
@TransactionalEventListener 不触发? | 检查 phase 与是否有活动事务,非事务上下文下需要 fallbackExecution | 7.1 |
延迟加载抛 LazyInitializationException? | 持久化上下文已关闭;用 JOIN FETCH / @EntityGraph 取够数据,而不是靠延长 open-in-view | 6.3 |
| Security 过滤器顺序不对、自定义 Filter 位置奇怪? | 用 @EnableWebSecurity(debug=true) 打印实际链,按 FilterOrderRegistration 的登记次序定位 | 8.1 |
| 方法级权限注解没拦住请求? | 确认 @EnableMethodSecurity 已开、表达式写对,并注意它同样受代理边界限制 | 8.3 |
| 想确认某个类在 4.x 的包路径变了没有? | 用 javap / unzip 直接查 jar,不要凭 3.x 的记忆写 import | 11.1、11.2 |
| 不确定某段结论是不是本机实测? | 涉及原生镜像、K8s、可观测性后端、async-profiler 的一律是「示例输出」,正文有显式标注 | 9.1–9.3、10.1–10.2 |
读完本卷之后
本卷覆盖的是 Spring Boot 的框架内部机制。读完之后,下面这些方向可以作为下一步。
如果想补齐工程交付能力,读实战卷。它讲模块拆分、依赖治理、测试分层、缓存一致性、连接池调优、容器化部署与上线回滚——本卷回答「框架内部怎么实现」,实战卷回答「生产上怎么选、代价是什么」。
如果需要查阅专题级深度,站内专题与本书是互补关系:本书是「按机制层次走一遍」,专题是「按主题深挖」。
- Java 专题 与 Java 企业级开发专题 :语言、并发、JVM 与 Spring Cloud 微服务方向。
- 架构专题 :架构风格、演进与权衡。
- 可观测性专题 :指标、日志、链路追踪的系统方法,与本卷第 10 章衔接。
- DevOps 专题 与 Kubernetes 专题 :CI/CD 与容器编排,与本卷第 9 章衔接。
- 书稿专题 :全部在线电子书与创作手记。
小结
这一页给出了全书的地图:34 篇的组织方式、四类读者的入口、三条阅读路径与一份八周计划、四个部分之间的依赖关系,以及 33 节的逐节索引与排查速查表。
如果你现在还不确定从哪开始,最稳妥的做法是:从第 1 章第 1 节开始,按顺序读,并且每一节都用 javap、unzip 或 --debug 亲手验一遍。高级卷的结论只有自己核实过才会变成判断力;只是读过一遍的机制描述,遇到真问题时还是想不起来。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。