Spring @Async的异常处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring @Async的异常处理相关的知识,希望对你有一定的参考价值。

楼主在前面的2篇文章中,分别介绍了Java子线程中通用的异常处理,以及Spring web应用中的异常处理。链接如下:

Java子线程中的异常处理(通用)

Spring web引用中的异常处理

今天,要写的是被Spring @Async注解的方法中的异常处理方法。

 

通常,如果我们要在程序中做一个耗时的操作(例如调用其他外部模块),一般会通过异步的方式执行。

有这2种方法:

  • 自行生成线程池ThreadPoolExecutor,提交任务执行
  • 更方便地,使用Spring @Async注解,修饰在需要异步执行的方法上

对于第一种方法的异常处理,楼主已经在“Java子线程中的异常处理(通用)”这篇文章中介绍了,也就是提交任务后获取到Future对象,通过future.get()获取返回值的时候能够捕获到ExcecutionException。

对于Spring @Async注解的方法,如何进行异常处理呢?楼主想到了2种方法。

解决办法

方法一:配置AsyncUncaughtExceptionHandler(对于无返回值的方法)

通过AsyncConfigurer自定义线程池,以及异常处理。

 1 @Configuration
 2 @EnableAsync
 3 public class SpringAsyncConfiguration implements AsyncConfigurer {
 4     private static final Logger logger = LoggerFactory.getLogger(getClass());
5 @Bean 6 @Override 7 public Executor getAsyncExecutor() { 8 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 9 executor.setCorePoolSize(8); 10 executor.setMaxPoolSize(16); 11 executor.setQueueCapacity(64); 12 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 13 executor.setThreadNamePrefix("SpringAsyncThread-"); 14 15 return executor; 16 } 17 18 @Override 19 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { 20 return new SpringAsyncExceptionHandler(); 21 } 22 23 class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { 24 @Override 25 public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { 26 logger.error("Exception occurs in async method", throwable.getMessage()); 27 } 28 } 29 30 }

方法二:通过AsyncResult捕获异常(对于有返回值的方法)

如果异步方法有返回值,那就应当返回AsyncResult类的对象,以便在调用处捕获异常。

因为AsyncResult是Future接口的子类,所以也可以通过future.get()获取返回值的时候捕获ExcecutionException。

异步方法:

@Service
public class AsyncService {

    @Async
    public AsyncResult<String> asyncMethodWithResult() {
        // do something(可能发生异常)

        return new AsyncResult("hello");
    }

}

调用处捕获异常:

 1 public class Test {
 2 
 3     private Logger logger = LoggerFactory.getLogger(getClass());
 4 
 5     @Autowired
 6     AsyncService asyncService;
 7 
 8     public void test() {
 9         try {
10             Future future = asyncService.asyncMethodWithResult();
11             future.get();
12         } catch (ExecutionException e) {
13             logger.error("exception occurs", e);
14         } catch (InterruptedException e) {
15             logger.error("exception occurs", e);
16         }
17     }
18 
19 }

 

以上是关于Spring @Async的异常处理的主要内容,如果未能解决你的问题,请参考以下文章

工作随笔——spring异步处理@Async使用笔记

Spring Boot中异步线程池@Async详解

使用 async/await 时在 Express 中捕获未处理的异常

在async / await中正确处理HttpClient异常

异常和TCP通讯

如何优雅地处理Async/Await的异常?