带有ListenableFuture的bean方法是否在单独的线程中执行返回值?

时间:2017-04-20 12:47:17

标签: java spring multithreading asynchronous

应用程序使用ListenableFuture<>返回类型的单一方法声明用于发送通知的接口。

对于邮件服务,如果我的批处理作业中配置错误(例如,如果SMTP服务器已关闭或主机未解析),我看不到异常。

调试显示在:

MailNotificationService mailService = applicationContext.getBean(MailNotificationService.class);

我收到了关于方法调用的代理:

mailService.send(mime);

用堆栈解决:

  at org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke(AsyncExecutionInterceptor.java:101)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)

invoke的文档说:

 * Intercept the given method invocation, submit the actual calling of the method to
 * the correct task executor and return immediately to the caller.

经过一些步骤后,我看到新的线程SimpleAsyncTaskExecutor-1和服务在这里执行。

看起来服务在单独的线程中执行,异常不会传播到原始线程(如果它有意义的话)。

对于ListenableFuture<>返回类型的bean方法,Spring是否正确在单独的线程中执行它们?

NB 我的原始问题是,如果通知服务出现错误,我将失明(未记录跟踪)。邮件服务抛出未经检查的org.springframework.mail.MailException,找到它的唯一方法是将.send()方法用Exception包裹日志:

@Autowired
private JavaMailSender mailSender;

public void notify() {
    try {
        mailSender.send(mime);
    } catch (Exception ex) {
        log.warn("Can't deliver mail", ex);
    }
}

1 个答案:

答案 0 :(得分:1)

正如 white 预测的那样,我在服务方法上有@Async注释,在配置类上有@EnableAsync。

部分中描述的异常处理:

http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#scheduling-annotation-support-exception

如果Future返回类型(ListenableFuture是其子类型),则异常传播到将来的对象,并且可以从ExecutionException.getCause()方法调用上发生的异常Future.get()中检索

在我的情况下,我忽略了返回类型(不要调用.get())。因此未捕获并记录异常。正如我在最初所写的那样,在这种情况下,应该在任务本身中执行excpetion logging。

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutionException.html