应用程序使用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);
}
}
答案 0 :(得分:1)
正如 white 预测的那样,我在服务方法上有@Async注释,在配置类上有@EnableAsync。
部分中描述的异常处理:
如果Future
返回类型(ListenableFuture
是其子类型),则异常传播到将来的对象,并且可以从ExecutionException.getCause()
方法调用上发生的异常Future.get()
中检索
在我的情况下,我忽略了返回类型(不要调用.get()
)。因此未捕获并记录异常。正如我在最初所写的那样,在这种情况下,应该在任务本身中执行excpetion logging。
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutionException.html