自定义方法注解实现事务完成后执行方法

     起因:有时候我们有这样的需求,在一个事务方法中调用了其他类的某个方法,但希望这个方法再事务提交后执行。

       思考:被调用的方法,肯定要做到延迟执行,可以把执行的方法放入ThreadLocal里,等事务提交后拿出来执行,但怎么判断事务已经提交了呢,这个就要用到spring 事务处理的AbstractPlatformTransactionManager类里面的回调功能

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
  try {
   boolean beforeCompletionInvoked = false;
   try {
    prepareForCommit(status);
    triggerBeforeCommit(status);
    triggerBeforeCompletion(status);
    beforeCompletionInvoked = true;
    boolean globalRollbackOnly = false;
    if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
     globalRollbackOnly = status.isGlobalRollbackOnly();
    }
    if (status.hasSavepoint()) {
     if (status.isDebug()) {
      logger.debug("Releasing transaction savepoint");
     }
     status.releaseHeldSavepoint();
    }
    else if (status.isNewTransaction()) {
     if (status.isDebug()) {
      logger.debug("Initiating transaction commit");
     }
     doCommit(status);
    }
    // Throw UnexpectedRollbackException if we have a global rollback-only
    // marker but still didn't get a corresponding exception from commit.
    if (globalRollbackOnly) {
     throw new UnexpectedRollbackException(
       "Transaction silently rolled back because it has been marked as rollback-only");
    }
   }
   catch (UnexpectedRollbackException ex) {
    // can only be caused by doCommit
    triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
    throw ex;
   }
   catch (TransactionException ex) {
    // can only be caused by doCommit
    if (isRollbackOnCommitFailure()) {
     doRollbackOnCommitException(status, ex);
    }
    else {
     triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
    }
    throw ex;
   }
   catch (RuntimeException ex) {
    if (!beforeCompletionInvoked) {
     triggerBeforeCompletion(status);
    }
    doRollbackOnCommitException(status, ex);
    throw ex;
   }
   catch (Error err) {
    if (!beforeCompletionInvoked) {
     triggerBeforeCompletion(status);
    }
    doRollbackOnCommitException(status, err);
    throw err;
   }

   // Trigger afterCommit callbacks, with an exception thrown there
   // propagated to callers but the transaction still considered as committed.
   try {
    triggerAfterCommit(status);
   }
   finally {
    triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
   }

  }
  finally {
   cleanupAfterCompletion(status);
  }
 }

 上面的trtriggerAfterCommit(status);就是处理事务提交后的动作处理,继续跟踪发现是调用

TransactionSynchronizationUtils 的下面方法

public static void invokeAfterCommit(List<TransactionSynchronization> synchronizations) {
  if (synchronizations != null) {
   for (TransactionSynchronization synchronization : synchronizations) {
    synchronization.afterCommit();
   }
  }
 }

synchronizations参数是通过 TransactionSynchronizationManager.getSynchronizations()获得的真是从ThreadLoca获取的对象是TransactionSynchronization。

  解决方法:自定义注解,在切面拦截有注解 的方法,并把待调用的方法封装到下面的这个类里并且执行execute方法,把当前方法设置到TransactionSynchronizationManager。最后再回调方法执行。

public class AfterCommitExecutorImpl extends TransactionSynchronizationAdapter implements AfterCommitExecutor {
    private static final Logger LOGGER = Logger.getLogger(AfterCommitExecutorImpl.class);
    private static final ThreadLocal<List<Runnable>> RUNNABLES = new ThreadLocal<List<Runnable>>();

    @Override
    public void execute(Runnable runnable) {
        LOGGER.info("Submitting new runnable {"+runnable+"} to run after commit");
        if (!TransactionSynchronizationManager.isSynchronizationActive()) {
            LOGGER.info("Transaction synchronization is NOT ACTIVE. Executing right now runnable {"+runnable+"}");
            runnable.run();
            return;
        }
        List<Runnable> threadRunnables = RUNNABLES.get();
        if (threadRunnables == null) {
            threadRunnables = new ArrayList<Runnable>();
            RUNNABLES.set(threadRunnables);
            TransactionSynchronizationManager.registerSynchronization(this);
        }
        threadRunnables.add(runnable);
    }

    @Override
    public void afterCommit() {
        List<Runnable> threadRunnables = RUNNABLES.get();
        LOGGER.info("Transaction successfully committed, executing {"+threadRunnables.size()+"} runnables" );
        for (int i = 0; i < threadRunnables.size(); i++) {
            Runnable runnable = threadRunnables.get(i);
            LOGGER.info("Executing runnable {"+runnable+"}");
            try {
                runnable.run();
            } catch (RuntimeException e) {
                LOGGER.error("Failed to execute runnable " + runnable, e);
            }
        }
    }

    @Override
    public void afterCompletion(int status) {
        LOGGER.info("Transaction completed with status {"+(status == STATUS_COMMITTED ? "COMMITTED" : "ROLLED_BACK")+"}");
        RUNNABLES.remove();
    }

猜你喜欢

转载自xuyunti.iteye.com/blog/2289501