Spring Async Uncaught Exception处理程序

@Override @Async public void asyncExceptionTest() { int i=1/0; } 

如何使用Spring Async框架进行日志记录,而不必在每个异步方法中放置try catch? 它似乎没有像普通的那样传递给DefaultUncaughtExceptionHandler

 @Configuration @EnableAsync public class ExampleConfig implements AsyncConfigurer { @Bean public Runnable testExec() { return new TestExec(); } @Override public Executor getAsyncExecutor() { final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("MyExecutor-"); executor.initialize(); return new HandlingExecutor(executor); } } public class HandlingExecutor implements AsyncTaskExecutor { private AsyncTaskExecutor executor; public HandlingExecutor(AsyncTaskExecutor executor) { this.executor = executor; } @Override public void execute(Runnable task) { executor.execute(task); } @Override public void execute(Runnable task, long startTimeout) { executor.execute(createWrappedRunnable(task), startTimeout); } @Override public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task)); } @Override public  Future submit(final Callable task) { return executor.submit(createCallable(task)); } private  Callable createCallable(final Callable task) { return new Callable() { @Override public T call() throws Exception { try { return task.call(); } catch (Exception e) { handle(e); throw e; } } }; } private Runnable createWrappedRunnable(final Runnable task) { return new Runnable() { @Override public void run() { try { task.run(); } catch (Exception e) { handle(e); } } }; } private void handle(Exception e) { System.out.println("CAUGHT!"); } } 

更新: 自Spring 4.1以来

从Spring 4.1开始,可以为@Async void方法提供@Async

Spring Reference Doc, 第34.4.5章使用@Async进行exception管理

…但是,对于void返回类型,exception未被捕获且无法传输。 对于这些情况,可以提供AsyncUncaughtExceptionHandler来处理此类exception。

默认情况下,只记录exception。 可以通过AsyncConfigurer或任务:注释驱动的XML元素定义自定义AsyncUncaughtExceptionHandler。

(这个function是在DD提出一个支持请求之后引入的: https ://jira.spring.io/browse/SPR-8995,请参阅此答案的评论)


在春季4.1之前

看起来像一个缺少的function如何处理返回@Async方法的voidexception。 (我在参考或java doc中找不到任何提示)

我能想象出一个解决方案:尝试使用AspectJ来编写某种包装器来解决所有记录exception的@Async方法。

对于日志术语,我建议在spring bug跟踪器中创建一个freature请求。

首先,您应该创建一个自定义exception处理程序类,如下所示;

 @Component public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler { private final Logger logger = LoggerFactory.getLogger(AsyncExceptionHandler.class); @Override public void handleUncaughtException(Throwable ex, Method method, Object... params) { logger.error("Unexpected asynchronous exception at : " + method.getDeclaringClass().getName() + "." + method.getName(), ex); } } 

之后,您应该在配置中设置自定义的exception处理程序类,如下所示;

 @Configuration @EnableAsync public class AsyncConfig extends AsyncConfigurerSupport { @Autowired private AsyncExceptionHandler asyncExceptionHandler; @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return asyncExceptionHandler; } } 

注意:可注入exception处理程序是一个选项。 您可以为每个例外创建一个新实例。 我的建议是使用Injection for exception handler class,因为spring的默认范围是singleton,因此不需要为每个exception创建新实例。