监听事务

  • java
  • spring
  • 事务

一、背景

项目中有很多给客户端发送点对点消息的代码,这些代码很多都被service里被@Transactional修饰的方法调用。

问题就出在这,有的时候事务可能还没完成提交,点对点消息可能就发出去了,客户端收到消息开始请求接口,请求到了旧数据。

这种情况就需要考虑将数据库操作与点对点消息进一步解耦了。

二、TransactionSynchronizationManager

TransactionSynchronizationManager提供了事务各阶段操作的回调。

public interface TransactionSynchronization extends Flushable {
	/** Completion status in case of proper commit. */
	int STATUS_COMMITTED = 0;
	/** Completion status in case of proper rollback. */
	int STATUS_ROLLED_BACK = 1;
	/** Completion status in case of heuristic mixed completion or system errors. */
	int STATUS_UNKNOWN = 2;

	default void suspend() {}

	default void resume() {}
    
	@Override
	default void flush() {}

	default void beforeCommit(boolean readOnly) {}

	default void beforeCompletion() {}

	default void afterCommit() {}
    
	default void afterCompletion(int status) {}
}

使用:

@Transactional
public void updateXXX(XXX x){
    
    // .......

    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
        @Override
        public void afterCommit() {
            System.out.println("事务提交后");
        }
    });
    // .......
}

三、TransactionalEventListener

3.1 定义事件

利用到了spring的事件机制,需要先定义事件:

public class CustomTransactionEvent extends ApplicationEvent {

    public CustomTransactionEvent(Object source) {
        super(source);
    }
}

3.2 定义listener

@Component
public class CustomTransactionListener {

    @TransactionalEventListener(
            //监听的事件
            classes=CustomTransactionEvent.class,
            //监听的事务阶段
            phase = TransactionPhase.AFTER_COMMIT,
            //无事务下是否执行此监听器
            fallbackExecution = true
    )
    public void sendMess(CustomTransactionEvent event){
        //...
    }
}

3.3 发布事件

@Transactional
public void updateXXX(XXX X){
    var event = new CustomTransactionEvent(x);
    applicationEventPublisher.publishEvent(event);
    // ...
}
Loading...