[英]How to add SynchronizationCallbacks to @TransactionalEventListener during spring boot application startup?
我有一个使用一些@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
的 Spring Boot 应用程序。 我注意到当它们最终抛出异常时,spring boot 不会为它们做任何异常记录。
因此,我想为此类异常添加一些通用日志记录工具。 我发现TransactionalApplicationListener.SynchronizationCallback
是我需要实现的接口。 然而,注册这些回调似乎很复杂。 我没有在 Spring 依赖项中找到任何可以实现此目的的TransactionalApplicationListener#addCallback
调用。
尝试获取TransactionalApplicationListener
列表和注入的SynchronizationCallback
,然后在@PostConstruct
中调用addCallback
并没有让我更进一步,因为即使应用程序确实成功使用了监听器,也始终没有注入监听器。
那么如何在 Spring Boot 应用程序启动期间将SynchronizationCallback
添加到TransactionalApplicationListener
中呢?
首先要注意的是, TransactionalApplicationListener
和所有ApplicationListener
一样不是 spring 上下文中的 bean。 他们生活在它之外(参见org.springframework.context.ConfigurableApplicationContext#addApplicationListener
)。 因此,对于应用程序上下文来说,注入它们是不可能的。
在调试和查看 spring 源代码时,发现这些侦听器是由org.springframework.transaction.event.TransactionalEventListenerFactory
创建的。 这就是我的解决方案所涉及的地方。 我们用另一个知道SynchronizationCallback
的工厂来装饰那个工厂:
public class SynchronizationCallbackAwareFactory implements EventListenerFactory, Ordered {
private final TransactionalEventListenerFactory delegate;
private final Provider<List<SynchronizationCallback>> synchronizationCallbacks;
private final int order;
public SynchronizationCallbackAwareFactory(TransactionalEventListenerFactory transactionalEventListenerFactory,
Provider<List<SynchronizationCallback>> synchronizationCallbacks,
int order) {
this.delegate = transactionalEventListenerFactory;
this.synchronizationCallbacks = synchronizationCallbacks;
this.order = order;
}
@Override
public boolean supportsMethod(Method method) {
return delegate.supportsMethod(method);
}
@Override
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
ApplicationListener<?> applicationListener = delegate.createApplicationListener(beanName, type, method);
if (applicationListener instanceof TransactionalApplicationListener) {
TransactionalApplicationListener<?> listener = (TransactionalApplicationListener<?>) applicationListener;
Collection<SynchronizationCallback> callbacks = this.synchronizationCallbacks.get();
callbacks.forEach(listener::addCallback);
}
return applicationListener;
}
@Override
public int getOrder() {
return order;
}
}
请注意,在我的案例中,我使用javax.inject.Provider
来在可能的最晚时间检索回调。
装饰器必须Ordered
,因为 spring 将使用第一个支持它所遇到的方法的工厂。 因此,此类实例的顺序必须具有更高的优先级,作为TransactionEventListenerFactory
的顺序值50
。
我对代码有类似的问题,如下所示
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class SomeListenerFacade {
@TransactionalEventListener
public void onSomething(SomeEvent event) {
throw new RuntimeException("some cause");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.