该技能聚焦 Spring Boot 3 下的异步执行(@Async)实践,适用于添加或调试异步工作、执行器饱和、异步失败或线程上下文丢失等场景。资料明确指出,它不是持久化作业的替代品。
基础环境方面,技能要求使用 Framework 6 API 与项目自身的 Boot BOM,随附示例在 Java 17 下编译。Boot 3.2+ 可在 Java 21 上选用虚拟线程,但更早的 Boot 3 版本不应作此假设,复制较新的任务执行属性前需确认具体次版本。
执行边界是首要判断:先确定进程退出时丢失工作是否可接受。内存内异步工作不是持久队列;必要的通知、支付和已接受的背景任务需要持久化意图加恢复机制,仅靠 AFTER_COMMIT 监听器或 HTTP 202 响应不足。已有消息代理或作业框架承担该契约时应保留它们。
启用异步拦截应只做一次,并通过代理调用独立的 Spring bean;同类内部调用不会变为异步。应使用命名执行器,调用方需观察失败时返回 CompletableFuture;void 方法需要 AsyncUncaughtExceptionHandler,因为调用方无法捕获其后续失败。提交阶段可能同步发生拒绝。
容量与生命周期上,线程数与排队工作应受下游容量和延迟目标约束。过大队列会掩盖过载并延迟增长超过核心池。应定义可见的拒绝结果,不静默丢弃必要工作。CallerRunsPolicy 可能把阻塞工作移到 HTTP 或事件循环线程,因此不是通用背压方案。自定义 Executor 可能改变 Boot 自动配置,需保留现有 applicationTaskExecutor 及 MVC/WebFlux 集成,示例仅选择 reportExecutor 并只覆盖该 worker。虚拟线程不增加数据库连接或远程配额,即使没有平台线程池也要限制未完成工作,并单独配置 I/O 超时与有界关闭。Future 取消/超时不能证明外部操作已停止。
状态与事务方面,应传递不可变 ID 或快照,而非请求对象、受管实体或懒加载集合。调用方线程绑定的事务不会随任务移动,worker 事务应放在独立代理服务中并在那里加载状态。提交前启动异步工作可能看到缺失数据;提交后派发仍有崩溃丢失窗口。租户、MDC 与安全状态需有意传播并清理,只捕获必要且可信的上下文,并在 finally 中恢复 worker 先前状态;操作需以提交方安全上下文运行时使用 Spring Security 的 delegating executor 支持;不要用可继承线程本地变量作为池级租户或认证策略。
验证应通过真实代理进行:worker 线程选择、失败 future、饱和拒绝与关闭。使用带截止时间的闩锁而非基于 sleep 的假设。用连续用户在同一 worker 上测试上下文清理,并在提交边界测试数据库可见性。需报告实际运行了哪些测试;提供的 fixture 不证明持久投递。
常见陷阱包括:在自身 @Async 方法上调用(应通过代理调用独立受管 bean);worker 内无执行器调用 supplyAsync(避免第二次 common-pool 跳转);把无界队列当做过载保护(应设置并测试显式容量预算);只捕获 future 失败(还需处理同步任务拒绝);假设 AFTER_COMMIT 加异步即保证投递(必要工作应持久化以便恢复);复制租户或安全状态而不清理(防止池化任务间泄漏)。
官方来源涉及 Boot 3 任务执行、Framework 6 调度与异步拦截、异步返回类型与执行器选择、ThreadPoolTaskExecutor 容量、Spring Security 并发支持及事务绑定事件。