Transaction-bound Events

从 Spring 4.2 开始,事件的监听器可以绑定到事务的一个阶段。一个典型的例子是在事务成功完成时处理事件。这样做可以让事件在当前事务的结果确实对监听器很重要时更加灵活地使用。

As of Spring 4.2, the listener of an event can be bound to a phase of the transaction. The typical example is to handle the event when the transaction has completed successfully. Doing so lets events be used with more flexibility when the outcome of the current transaction actually matters to the listener.

你可以使用 @EventListener 注释来注册常规事件监听器。如果你需要将其绑定到事务,请使用 @TransactionalEventListener。当你这样做时,监听器默认绑定到事务的提交阶段。

You can register a regular event listener by using the @EventListener annotation. If you need to bind it to the transaction, use @TransactionalEventListener. When you do so, the listener is bound to the commit phase of the transaction by default.

下一个示例展示了这个概念。假设某个组件发布了一个 order-created 事件,并且我们想要定义一个监听器,它只在发布它的事务成功提交后才处理该事件。以下示例设置了一个这样的事件监听器:

The next example shows this concept. Assume that a component publishes an order-created event and that we want to define a listener that should only handle that event once the transaction in which it has been published has committed successfully. The following example sets up such an event listener:

  • Java

  • Kotlin

@Component
public class MyComponent {

	@TransactionalEventListener
	public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) {
		// ...
	}
}
@Component
class MyComponent {

	@TransactionalEventListener
	fun handleOrderCreatedEvent(creationEvent: CreationEvent<Order>) {
		// ...
	}
}

@TransactionalEventListener 注释公开了一个 phase 属性,允许你自定义监听器应该绑定的事务阶段。有效阶段有 BEFORE_COMMITAFTER_COMMIT(默认)、AFTER_ROLLBACK 以及 AFTER_COMPLETION,它汇总了事务完成(无论它是提交还是回滚)。

The @TransactionalEventListener annotation exposes a phase attribute that lets you customize the phase of the transaction to which the listener should be bound. The valid phases are BEFORE_COMMIT, AFTER_COMMIT (default), AFTER_ROLLBACK, as well as AFTER_COMPLETION which aggregates the transaction completion (be it a commit or a rollback).

如果没有事务正在运行,那么根本不会调用该监听器,因为我们无法尊重必需的语义。但是,你可以通过将注释的 fallbackExecution 属性设置为 true 来覆盖该行为。

If no transaction is running, the listener is not invoked at all, since we cannot honor the required semantics. You can, however, override that behavior by setting the fallbackExecution attribute of the annotation to true.

从 6.1 开始,@TransactionalEventListener 可以与由 PlatformTransactionManager 管理的线程绑定事务以及由 ReactiveTransactionManager 管理的反应式事务一起使用。对于前者,监听器一定会看到当前的线程绑定事务。由于后者使用 Reactor 上下文而不是线程局部变量,因此事务上下文需要作为事件源包含在发布的事件实例中。有关详细信息,请参阅https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/reactive/TransactionalEventPublisher.html[TransactionalEventPublisher] javadoc。

As of 6.1, @TransactionalEventListener can work with thread-bound transactions managed by PlatformTransactionManager as well as reactive transactions managed by ReactiveTransactionManager. For the former, listeners are guaranteed to see the current thread-bound transaction. Since the latter uses the Reactor context instead of thread-local variables, the transaction context needs to be included in the published event instance as the event source. See the TransactionalEventPublisher javadoc for details.