我正在同步使用 Guava EventBus。如果任何订阅者抛出异常,我如何回滚整个事务?如何抛出一个不会被 EventBus 订阅者捕获的异常?
最佳答案
您所要做的就是查看 Guava 的 EventBus
类的源代码。
让我们从最后开始:
How can I throw an Exception which will not be caught by the EventBus Subscriber?
订阅者的方法由 com.google.common.eventbus.Dispatcher#dispatch
方法依次调用。为了调用订阅者的方法,EventBus 使用反射的方法 Method#invoke
,如果被调用的方法抛出异常,该方法会抛出 InvokingTargetException
。
正如您所看到的,InitationTargetException
(它将包裹在您的Exception
周围)的处理如下:
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw e;
}
在上层,异常的处理方式如下:
try {
invokeSubscriberMethod(event);
} catch (InvocationTargetException e) {
bus.handleSubscriberException(e.getCause(), context(event));
}
TL;DR
因此,省略 EventBus
异常处理程序的唯一方法是在订阅方法中抛出 Error
,而不是 Exception
- 当然是这样不好的做法。
How can I rollback the complete transaction if any of the subscribers throw an Exception?
EventBus
异常处理程序通过调用 com.google.common.eventbus.EventBus#handleSubscriberException
方法来处理异常。它看起来像这样:
try {
exceptionHandler.handleException(e, context);
} catch (Throwable e2) {
// logging
}
因此,从异常处理程序抛出的任何异常都无济于事。您有两个选择:
- 要么从订阅者方法中抛出错误(这太糟糕了)
- 或者从该流程中的任何位置手动将事务设置为仅回滚。我认为处理此类事情的最佳位置显然是
EventBus
异常处理程序。
关于java - 从 Guava EventBus 订阅者抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37974801/