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"),指定使用上述自定义线程池。

注意:

  1. 启动类需添加@EnableAsync
  2. 异步方法必须在另一个类中调用(自调用无效),因为 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();}}

四、关键注意事项

  1. 返回值类型:@Async方法若需返回结果,必须返回CompletableFuture<T>Future<T>,否则调用方无法获取返回值。
  2. 异常处理:异步方法中的异常不会直接抛出到 Controller。建议配置全局AsyncUncaughtExceptionHandler或在CompletableFuture链中处理。
  3. 事务问题:@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 容器

在配置类中重写getAsyncExecutorgetAsyncUncaughtExceptionHandler方法。

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,需在链式调用末尾添加exceptionallyhandle,确保业务级异常被捕获。

future.thenApply(res->process(res)).exceptionally(ex->{log.error("业务处理失败",ex);returndefaultResult;// 返回默认值,防止链路中断});

四、核心区别总结

场景异常捕获方式适用情况
@Async 无返回值AsyncUncaughtExceptionHandler简单通知、日志记录等“发了就不管”的场景。
CompletableFuture.exceptionally()/.handle()需要获取结果、进行业务补偿或降级的场景。
Controller 层@RestControllerAdvice无效。无法捕获异步线程抛出的异常。