《Spring Boot 实战》10.2 消息队列集成
以 Spring Kafka 为主、RabbitMQ 为对照,讲清借阅事件通知的生产端与消费端落地:starter 与模块化依赖、序列化选型、@KafkaListener 容器工厂与并发度、消费位点提交模式、批量消费,以及生产端发送回调与分区顺序保证。
tag
以 Spring Kafka 为主、RabbitMQ 为对照,讲清借阅事件通知的生产端与消费端落地:starter 与模块化依赖、序列化选型、@KafkaListener 容器工厂与并发度、消费位点提交模式、批量消费,以及生产端发送回调与分区顺序保证。
从 spring.factories 到 AutoConfiguration.imports,逐层拆开 Spring Boot 4 自动配置类的发现、过滤与排序:AutoConfigurationSorter 如何在 @AutoConfigureBefore/@AutoConfigureAfter 与 @AutoConfigureOrder 之上做拓扑排序,以及为何还要用全限定名做兜底。
讲清 @Async 的代理前提与自调用失效,说明默认 SimpleAsyncTaskExecutor 为何不能上生产,给出自定义 ThreadPoolTaskExecutor、TaskDecorator 上下文传递、有界队列与拒绝策略、CompletableFuture 异常的落地写法,并分析虚拟线程对线程池选型的影响。
图书、作者、分类之间天然存在关联。本节用图书服务演示 @OneToOne、@OneToMany、@ManyToOne、@ManyToMany 四种映射,讲清 mappedBy 与关系维护方、@JoinColumn 指定外键、级联与 orphanRemoval 的取舍,并用 show-sql 直观演示 N+1 问题。
走完 getBean() 到 doCreateBean 的解析链:用字节码调用次序说明三级缓存 singletonObjects / earlySingletonObjects / singletonFactories 为何能解掉 setter 循环依赖、构造器循环依赖为何必然失败,并对比 @Lazy 与 ObjectProvider 破环的代价。
用 @EnableMethodSecurity 与 @PreAuthorize/@PostAuthorize 做方法级授权,设计 RBAC 与资源级权限,并在分馆租户模型下比较租户字段过滤、schema 隔离与库隔离的取舍,解决租户上下文在异步线程中的传播与越权测试。
BeanDefinition 是容器持有的元数据契约:本节拆开 AbstractBeanDefinition 的字段结构、BeanDefinitionRegistry 的注册与覆盖判定、组件扫描与 @Configuration 解析如何产出定义,讲清父子定义合并成 RootBeanDefinition 的过程,以及 @Primary 与别名在候选筛选里的作用。
对比无状态与 Session 在水平扩展、注销与吊销上的取舍,给出 HS256 与 RS256 的选型判据,用 JwtDecoder/JwtEncoder 落地签发与校验、token 过期与刷新轮换、密钥轮换与 kid,并列出算法混淆、none 算法等安全错误。
从 SpringApplication.run() 追到 ApplicationContext 可用:拆开 refresh() 的十二个步骤各自做了什么,标出 BeanFactoryPostProcessor 与 BeanPostProcessor 的介入时机,把本机实测启动日志逐行对回框架阶段,并给出断点位置与扩展点清单。
从 SecurityFilterChain bean 与 lambda DSL 讲起,梳理 4.x 的 Security starter 改名、过滤器链的执行顺序与各自职责、401 与 403 的分工、密码编码器与 UserDetailsService 的落地写法,并给出多链共存的常见配置陷阱。
本节把图书服务的查询需求变成方法名:讲清 findBy/readBy 等前缀与条件关键字的语法规则,给出 And、Between、Containing、In、OrderBy、IgnoreCase、Top 等关键字全表,说明属性路径导航与 @Query 的取舍,并用 @Modifying 实现更新删除、用投影接口只取需要的列。
缓存最难的从来不是怎么放,而是数据变了以后怎么办:讲清 Cache-Aside 的读写顺序为何推荐先写库再删缓存、延迟双删与订阅 binlog 各自换来了什么、穿透击穿雪崩三种故障的对策、缓存与事务边界如何对齐,以及一致性要求高时「不用缓存」这个正当选项。
把图书借阅服务的缓存落到 Redis:接入 starter、选序列化方案并厘清与 4.x Jackson 3 的关系、Lettuce 共享连接与 Jedis 池的取舍、键命名与内存估算、大 key 与热 key 的危害,以及 4.1 新增的 @RedisListener 自动配置。
把缓存声明式地加到图书借阅服务上:讲清 @Cacheable / @CachePut / @CacheEvict / @Caching 的语义差异、key 与 SpEL 的写法陷阱、condition 与 unless 的执行时机、CacheManager 与多级缓存配置,以及同类内部调用失效和 TTL 表达边界。
本节把 record 版 Book 改造成 JPA 实体:讲透 @Entity、@Id、@GeneratedValue、@Column、@Table 与主键生成策略的取舍,说清为什么实体不能用 record 而 record 适合做 DTO,梳理 CrudRepository 与 JpaRepository 的继承关系,并给出实体 equals/hashCode 的可靠写法。
对比 URL、Header、媒体类型三种版本载体的取舍,讲清 Spring Boot 4 内置 API Versioning 的 spring.mvc.apiversion.* 属性、@GetMapping(version=...) 注解与 ApiVersionConfigurer 精细控制,给出向后兼容判定清单、Deprecation/Sunset 废弃流程与破坏性变更的并行发布策略。
把 OpenAPI 文件从代码的产物变成代码的输入:用 openapi-generator 7.26 生成接口与 DTO,用 interfaceOnly 与生成目录划清生成与手写的边界,给出避免重生成覆盖业务逻辑的三条纪律,并在 CI 里用 validate、spectral、漂移检查与 oasdiff 四道关固定契约。
讲清 Spring Boot 4 下 springdoc-openapi 3.x 的依赖坐标与版本线,用 @Operation、@Schema、@ApiResponse 补齐接口语义,划清推断与注解的边界,用 GroupedOpenApi 拆分前台与后台文档,并给出生产环境关闭文档或加鉴权的两种收口方式与四类常见坑。
本节把图书管理服务从内存 Map 换到真正的数据库:引入 spring-boot-starter-data-jpa 与 H2、MySQL 驱动,逐项讲清 spring.datasource.* 与 HikariCP 关键参数的默认值,用表格对比 ddl-auto 四个取值的风险,并演示 4.1 新增的惰性连接获取与启动期连不上库的真实报错。
N+1 是 JPA 生产事故的头号来源。本节从 SQL 日志里还原 N+1 的形态,对比 JOIN FETCH、@EntityGraph 与 @BatchSize 三种抓取策略的代价,讲清分页叠加 fetch join 的经典陷阱与 LazyInitializationException 的根因,并给出定位与验收方法。