樓主在前面的2篇文章中,分別介紹了Java子線程中通用的異常處理,以及Spring web應(yīng)用中的異常處理。鏈接如下:
Java子線程中的異常處理(通用)
Spring Boot應(yīng)用中的異常處理
今天,要寫的是被Spring @Async注解的方法中的異常處理方法。
通常,如果我們要在程序中做一個耗時的操作(例如調(diào)用其他外部模塊),一般會通過異步的方式執(zhí)行。
有這2種方法:
- 自行生成線程池ThreadPoolExecutor,提交任務(wù)執(zhí)行
- 更方便地,使用Spring @Async注解,修飾在需要異步執(zhí)行的方法上
對于第一種方法的異常處理,樓主已經(jīng)在“Java子線程中的異常處理(通用)”這篇文章中介紹了,也就是提交任務(wù)后獲取到Future對象,通過future.get()獲取返回值的時候能夠捕獲到ExcecutionException。
對于Spring @Async注解的方法,如何進(jìn)行異常處理呢?樓主想到了2種方法。
解決辦法
方法一:配置AsyncUncaughtExceptionHandler(對于無返回值的方法)
通過AsyncConfigurer自定義線程池,以及異常處理。
@Configuration@EnableAsyncpublic class SpringAsyncConfiguration implements AsyncConfigurer { private static final Logger logger = LoggerFactory.getLogger(getClass()); @Bean @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(8); executor.setMaxPoolSize(16); executor.setQueueCapacity(64); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setThreadNamePrefix(“SpringAsyncThread-“); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new SpringAsyncExceptionHandler(); } class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable throwable, Method method, Object… obj) { logger.error(“Exception occurs in async method”, throwable.getMessage()); } }}
方法二:通過AsyncResult捕獲異常(對于有返回值的方法)
如果異步方法有返回值,那就應(yīng)當(dāng)返回AsyncResult類的對象,以便在調(diào)用處捕獲異常。
因為AsyncResult是Future接口的子類,所以也可以通過future.get()獲取返回值的時候捕獲ExcecutionException。
異步方法:
@Servicepublic class AsyncService { @Async public AsyncResult asyncMethodWithResult() { // do something(可能發(fā)生異常) return new AsyncResult(“hello”); }}
調(diào)用處捕獲異常:
public class Test { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired AsyncService asyncService; public void test() { try { Future future = asyncService.asyncMethodWithResult(); future.get(); } catch (ExecutionException e) { logger.error(“exception occurs”, e); } catch (InterruptedException e) { logger.error(“exception occurs”, e); } }}