卫生局网站建设实施方案,长沙网站建设公司哪家专业,做网站哪里比较好,深圳做外贸的公司在事务还没有执行完消息就已经发出去了, 导致后续的一些数据或逻辑上的问题产生。场景如下#xff1a;异步-记录日志#xff1a;当事务提交后#xff0c;再记录日志。发送mq消息#xff1a;只有业务数据都存入表后#xff0c;再发mq消息。方案1. 利用TransactionSynchroni…在事务还没有执行完消息就已经发出去了, 导致后续的一些数据或逻辑上的问题产生。场景如下异步-记录日志当事务提交后再记录日志。发送mq消息只有业务数据都存入表后再发mq消息。方案1. 利用TransactionSynchronizationManager的registerSynchronization()方法注册TransactionSynchronization实现类我们只需要在执行的事务方法中, 添加如下代码, 就可以完成在事务提交后的逻辑处理了// TransactionSynchronizationAdapter是TransactionSynchronization的默认实现
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {Overridepublic void afterCommit() {// 事务提交后需要执行的业务逻辑: 发消息, 日志...}
});
原理Spring 事务的扩展 – TransactionSynchronization事务操作的时候它的当前线程还保存了 TransactionSynchronization 对象。而这个对象伴随着 Spring 对 事务处理的各个生命周期都会有相应的扩展public interface TransactionSynchronization extends Flushable {/** 事务提交状态 */int STATUS_COMMITTED 0;/** 事务回滚状态 */int STATUS_ROLLED_BACK 1;/**系统异常状态 */int STATUS_UNKNOWN 2;void suspend();void resume();void flush();// 事务提交之前void beforeCommit(boolean readOnly);// 事务成功或者事务回滚之前void beforeCompletion();// 事务成功提交之后void afterCommit();// 操作完成之后(包含事务成功或者事务回滚)void afterCompletion(int status);}事务的事务扩展项目中的应用场景是当订单成功之后发送一条消息到 MQ 当中去。由于事务是和数据库连接相绑定的如果把发送消息和数据库操作放在一个事务里面。当发送消息时间过长时会占用数据库连接所以就要把数据库操作与发送消息到 MQ 解耦开来。可以利用 TransactionSynchronization#afterCommit 的这个方法当数据成功保存到数据库并且事务提交了就把消息发送到 MQ 里面。Transactional
public void finishOrder(Order order){// 修改订单成功updateOrderSuccess(order);// 发送消息到 MQTransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){Overridepublic void afterCommit() {mqService.send(order);}});
}当事务成功提交之后就会把消息发送给 MQ并且不会占用数据库连接资源。方式二、Spring 事务扩展 – TransactionalEventListener在 Spring framework 4.2 之后还可以使用TransactionalEventListener处理数据库事务提交成功后再执行操作。这种方式比 TransactionSynchronization 更加优雅。它的使用方式如下Autowired
private ApplicationEventPublisher publisher;Override
Transactional(rollbackFor Exception.class)
public void add(AdvanceChargeApplyAddInput input) {this.save(advanceChargeApply);// 发送事件publisher.publishEvent(advanceChargeApply);
}
// 响应事件, 事务提交后执行
TransactionalEventListener
public void handle(PayloadApplicationEventAdvanceChargeApply event) {System.out.println(TransactionalEventListener 事务提交后执行);
}也可以自定义事件源和事件监听 Transactionalpublic void finishOrder(Order order){// 修改订单成功updateOrderSuccess(order);// 发布 Spring Event 事件applicationEventPublisher.publishEvent(new MyAfterTransactionEvent(order));}Slf4jComponentprivate static class MyTransactionListener {Autowiredprivate MqService mqService;TransactionalEventListener(phase TransactionPhase.AFTER_COMMIT)private void onHelloEvent(MyAfterTransactionEvent event) {Order order event.getOrder();mqService.send(order);}}// 定一个事件继承自ApplicationEvent private static class MyAfterTransactionEvent extends ApplicationEvent {private Order order;public MyAfterTransactionEvent(Object source, Order order) {super(source);this.order order;}public Order getOrder() {return order;}}它的实现原理是当 Spring Bean 的方法标注了通过 TransactionalEventListenerFactory#createApplicationListener创建 ApplicationListenerMethodTransactionalAdapter 然后在事件回调当中创建 TransactionSynchronization的实现类TransactionSynchronizationEventAdapter。并且通过 TransactionSynchronizationManager.registerSynchronization把 TransactionSynchronizationEventAdapter 注册到当前线程当中。TransactionSynchronizationEventAdapter private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter {private final ApplicationListenerMethodAdapter listener;private final ApplicationEvent event;private final TransactionPhase phase;public TransactionSynchronizationEventAdapter(ApplicationListenerMethodAdapter listener,ApplicationEvent event, TransactionPhase phase) {this.listener listener;this.event event;this.phase phase;}Overridepublic int getOrder() {return this.listener.getOrder();}Overridepublic void beforeCommit(boolean readOnly) {if (this.phase TransactionPhase.BEFORE_COMMIT) {processEvent();}}Overridepublic void afterCompletion(int status) {if (this.phase TransactionPhase.AFTER_COMMIT status STATUS_COMMITTED) {processEvent();}else if (this.phase TransactionPhase.AFTER_ROLLBACK status STATUS_ROLLED_BACK) {processEvent();}else if (this.phase TransactionPhase.AFTER_COMPLETION) {processEvent();}}protected void processEvent() {this.listener.processEvent(this.event);}}