首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Spring Async未捕获异常处理程序

Spring Async未捕获异常处理程序
EN

Stack Overflow用户
提问于 2012-01-05 08:00:14
回答 4查看 32.5K关注 0票数 28
代码语言:javascript
代码运行次数:0
运行
复制
@Override
@Async
public void asyncExceptionTest() {
    int i=1/0;
}

我如何使用Spring Async框架来记录这一点,而不必在每个异步方法中都放入try catch?它似乎不会像正常的那样传递给DefaultUncaughtExceptionHandler

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-28 21:57:05

可以使用自定义Executor配置@Async方法,以记录任何抛出的异常。

下面的代码实现了这个模式。任何用@Async标记的方法都将使用由方法public Executor getAsyncExecutor()返回的Executor。这将返回负责所有日志记录的HandlingExecutor (在本例中,它只打印单词"CAUGHT!“但您可以将其替换为日志。

代码语言:javascript
代码运行次数:0
运行
复制
@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 <T> Future<T> submit(final Callable<T> task) {
        return executor.submit(createCallable(task));
    }

    private <T> Callable<T> createCallable(final Callable<T> task) {
        return new Callable<T>() {
            @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!");
    }
}
票数 24
EN

Stack Overflow用户

发布于 2012-01-05 16:35:31

更新:自4.1Spring以来的

从Spring4.1开始,可以为@Async void方法提供一个AsyncUncaughtExceptionHandler

Spring参考文档,Chapter 34.4.5 Exception management with @Async

...然而,对于void返回类型,异常是未捕获的,并且不能传输。对于这些情况,可以提供一个AsyncUncaughtExceptionHandler来处理此类异常。

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

(此功能是在DD提出改进请求后引入的:,请参阅此答案的评论)

Spring 4.1之前的

看起来缺少如何处理返回@Async方法的void异常的功能。(我在参考资料或java文档中找不到任何提示)

我能想到的解决方案是:尝试使用AspectJ在记录异常的所有@Async方法周围编写某种包装器。

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

票数 21
EN

Stack Overflow用户

发布于 2017-10-20 21:57:22

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

代码语言:javascript
代码运行次数:0
运行
复制
@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);
        }

    }

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

代码语言:javascript
代码运行次数:0
运行
复制
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

    @Autowired
    private AsyncExceptionHandler asyncExceptionHandler;

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return asyncExceptionHandler;
    }

}

注意:可注入异常处理程序是一个选项。您可以为每个异常创建一个新实例。我的建议是对异常处理程序类使用注入,因为spring的默认作用域是singleton,所以没有必要为每个异常创建新的实例。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8735870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档