Spring Boot 集成自定义线程池和异常处理
Spring Boot 集成自定义线程池和异常处理
- 1.Spring Boot 集成自定义线程池
- 一、配置自定义线程池
- 二、使用 @Async 实现声明式异步
- 三、Controller 中编排异步结果
- 四、关键注意事项
- 2.Spring Boot 异步全局异常处理
- 一、自定义异常处理器
- 二、注册到 Spring 容器
- 三、CompletableFuture 的异常处理
- 四、核心区别总结
1.Spring Boot 集成自定义线程池
在 Spring Boot 中,通过@Configuration配置 Bean,并结合@Async注解或手动注入ThreadPoolTaskExecutor,可实现声明式异步调用。
一、配置自定义线程池
创建配置类,定义ThreadPoolTaskExecutorBean,确保参数可控且线程命名规范。
importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;importjava.util.concurrent.ThreadPoolExecutor;@ConfigurationpublicclassAsyncConfig{@Bean("bizTaskExecutor")publicThreadPoolTaskExecutortaskExecutor(){ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("biz-async-");// 拒绝策略:由调用线程执行,起到背压作用executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());executor.initialize();returnexecutor;}}二、使用 @Async 实现声明式异步
在 Service 层方法上添加@Async("bizTaskExecutor"),指定使用上述自定义线程池。
注意:
- 启动类需添加
@EnableAsync。 - 异步方法必须在另一个类中调用(自调用无效),因为 Spring AOP 基于代理。
importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;importjava.util.concurrent.CompletableFuture;@ServicepublicclassOrderService{@Async("bizTaskExecutor")publicCompletableFuture<String>queryUserAsync(){try{Thread.sleep(1000);}catch(InterruptedExceptione){}returnCompletableFuture.completedFuture("User_1001");}@Async("bizTaskExecutor")publicCompletableFuture<String>queryOrderAsync(){try{Thread.sleep(1200);}catch(InterruptedExceptione){}returnCompletableFuture.completedFuture("Order_List");}}三、Controller 中编排异步结果
在 Controller 中注入 Service,利用CompletableFuture组合多个异步任务的结果。
importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.concurrent.CompletableFuture;@RestControllerpublicclassOrderController{@AutowiredprivateOrderServiceorderService;@GetMapping("/order/detail")publicStringgetOrderDetail()throwsException{// 并行发起两个异步请求CompletableFuture<String>userFuture=orderService.queryUserAsync();CompletableFuture<String>orderFuture=orderService.queryOrderAsync();// 等待所有任务完成并合并结果CompletableFuture.allOf(userFuture,orderFuture).join();return"用户: "+userFuture.get()+", 订单: "+orderFuture.get();}}四、关键注意事项
- 返回值类型:
@Async方法若需返回结果,必须返回CompletableFuture<T>或Future<T>,否则调用方无法获取返回值。 - 异常处理:异步方法中的异常不会直接抛出到 Controller。建议配置全局
AsyncUncaughtExceptionHandler或在CompletableFuture链中处理。 - 事务问题:
@Async方法默认不在主事务中运行。若需事务,需在异步方法内部单独开启@Transactional。
2.Spring Boot 异步全局异常处理
在 Spring Boot 中,@Async方法的异常无法被 Controller 的@ExceptionHandler捕获。需配置AsyncUncaughtExceptionHandler进行统一兜底,防止异常静默丢失。
一、自定义异常处理器
实现AsyncUncaughtExceptionHandler接口,记录日志或发送告警。
importorg.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;importlombok.extern.slf4j.Slf4j;importjava.lang.reflect.Method;@Slf4jpublicclassCustomAsyncExceptionHandlerimplementsAsyncUncaughtExceptionHandler{@OverridepublicvoidhandleUncaughtException(Throwableex,Methodmethod,Object...params){log.error("异步任务异常 - 方法: {}, 参数: {}",method.getName(),params,ex);// 此处可集成监控告警(如 Sentry/Prometheus)}}二、注册到 Spring 容器
在配置类中重写getAsyncExecutor和getAsyncUncaughtExceptionHandler方法。
importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.annotation.AsyncConfigurer;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;importjava.util.concurrent.Executor;@ConfigurationpublicclassAsyncConfigimplementsAsyncConfigurer{@OverridepublicExecutorgetAsyncExecutor(){ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix("biz-async-");executor.initialize();returnexecutor;}@OverridepublicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){returnnewCustomAsyncExceptionHandler();}}三、CompletableFuture 的异常处理
若使用CompletableFuture,需在链式调用末尾添加exceptionally或handle,确保业务级异常被捕获。
future.thenApply(res->process(res)).exceptionally(ex->{log.error("业务处理失败",ex);returndefaultResult;// 返回默认值,防止链路中断});四、核心区别总结
| 场景 | 异常捕获方式 | 适用情况 |
|---|---|---|
| @Async 无返回值 | AsyncUncaughtExceptionHandler | 简单通知、日志记录等“发了就不管”的场景。 |
| CompletableFuture | .exceptionally()/.handle() | 需要获取结果、进行业务补偿或降级的场景。 |
| Controller 层 | @RestControllerAdvice | 无效。无法捕获异步线程抛出的异常。 |