有时我们需要在某一方法事务提交后再执行一些操作,这些操作可能涉及到提交的数据,如要查询上一步提交后的数据这种 情况,这时我们希望能实现在上一步事务提交后再执行后面的操作。
Spring 中可以使用 ApplicationEvent 事件监听来实现事务监听。

新建事件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**

@Description 待办任务状态推送事件
@Date 2021/01/05 15:41
@Author jiangwei.huang@hand-china.com
*/
public class TodoPushEvent extends ApplicationEvent {
private List processTaskInfos;
public TodoPushEvent(Object source, List processTaskInfos) {
super(source);
this.processTaskInfos = processTaskInfos;
}
public List getProcessTaskInfos() {
return processTaskInfos;
}
}

新建事件监听器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**

@Description 待办任务状态推送监听器
@Date 2021/01/05 15:42
@Author jiangwei.huang@hand-china.com
*/
@Component
@Slf4j
public class TodoPushListener {
@Autowired
private IYnjtTaskSendService iYnjtTaskSendService;
private static final Logger LOGGER = LoggerFactory.getLogger(TodoPushListener.class);
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void onApplicationEvent(TodoPushEvent todoPushEvent){
List processTaskInfos = todoPushEvent.getProcessTaskInfos();
Task taskEntity = (Task) todoPushEvent.getSource();
//排除当前待办任务
List taskInfos = processTaskInfos.stream().filter(processTaskInfo -> !StringUtils.equals(processTaskInfo.getId(),taskEntity.getId()) )
.collect(Collectors.toList());
//推送当前已完成的待办
YnjtTaskDTO ynjtTaskDTO = new YnjtTaskDTO().setTaskId(Long.parseLong(taskEntity.getId())).setProcInstId(Long.parseLong(taskEntity.getProcessInstanceId())).setAction("COMPLETE");
iYnjtTaskSendService.sendApprovedTask(Collections.singletonList(ynjtTaskDTO));
try {
//推送待办
iYnjtTaskSendService.sendTasks(null, Long.parseLong(taskEntity.getTenantId()), taskEntity.getProcessInstanceId(), "P", taskInfos);
}catch (Exception e){
LOGGER.error(taskEntity.getProcessInstanceId() + "审批后生成下一节点的待办推送失败:" + e.getMessage());
}
}

}
  • onApplicationEvent方法中的参数为上面新建的事件类。
  • 加上 @TransactionalEventListener 注解,TransactionPhase.AFTER_COMMIT 表示在上个事务提交之前再执行。

事件调用

其它事务方法中调用即可,可实现当前方法事务提前后再 执行该事件监听的执行内容。

因此调用的方法必须是有事务的,即使用@Transactional进行注解了,这样事务监听才会生效

1
2
//当前事务提交后推送待办状态到IAM
applicationEventPublisher.publishEvent(new TodoPushEvent(taskEntity,processTaskInfos));