我正在尝试使用一个 @TransactionalEventListener
(Spring 4.3),它将在事务完成后运行一个事件。
但是,我有自己的 ApplicationEventMulticaster
,我正在构建并使用 ThreadPoolTaskExecutor
。
SimpleApplicationEventMulticaster
状态的文档:
/**
* Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
* to invoke each listener with.
* <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
* executing all listeners synchronously in the calling thread.
* <p>Consider specifying an asynchronous task executor here to not block the
* caller until all listeners have been executed. However, note that asynchronous
* execution will not participate in the caller's thread context (class loader,
* transaction association) unless the TaskExecutor explicitly supports this.
* @see org.springframework.core.task.SyncTaskExecutor
* @see org.springframework.core.task.SimpleAsyncTaskExecutor
*/
public void setTaskExecutor(Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
但是,我无法找到事务感知的 Async TaskExecutor
。 Java 生态系统中是否已经存在这样的东西?
目前,我的事件从未运行过,因为 ThreadPoolTaskExecutor
不了解事务,因此它始终认为没有当前事务 - 忽略事件监听器。
最佳答案
不,目前稳定的 TaskExecutor
将与 spring 管理的事务一起工作,目前 Spring 通过 ThreadLocals 将事务绑定(bind)到线程。
但您只需在 @TransactionalEventListener
监听器方法上添加 @Async
注释,即可轻松地在代码中使用异步 @TransactionalEventListener
。请记住,仅当在事务边界及其后提交阶段调用发布者时,Spring 才会将事件发布给监听器,但事务已完成,因此对象处于分离状态。
假设您需要从事务中发布事件
@Service
public class Service {
@Autowired
private SomeRepository someRepository;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Transactional
public void create(SomeEntity entity) {
someRepository.save(entity);
SomeEntityCreatedEvent event = new SomeEntityCreatedEvent();
event.entity = entity;
applicationEventPublisher.publishEvent(event);
}
public static final class SomeEntityCreatedEvent {
private SomeEntity entity;
public SomeEntity getSomeEntity() {
return entity;
}
}
}
监听器将获得具有已分离实体的事件,因此不会将其更改传播到数据存储区。
@Component
public class UpdatesListener {
@Async // here you can controll the task executor which needs to take care of this thread
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleCustom(Service.SomeEntityCreatedEvent event) {
// here entity is deatached
SomeEntity entity = event.getSomeEntity();
System.out.println("Created some entity with id" + entity.getId());
}
}
啊,不要覆盖 SimpleApplicationEventMulticaster
上的默认 SyncTaskExecutor
,而是在监听器上使用 @Async
。
关于支持事务关联的 Java 或 Spring async TaskExeuctor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60976077/