spring事务

spring事务多重要,这个真的是很绝,本来我不准备写,结果看到些资料,不写感觉对不起自己个儿,所以这篇来了! 直接上个干货;

spring事务

   基于数据库事务和AOP机制

   @Transaction注解,创建代理,调用代理方法判断是否加了注解

   加了 事务管理器 创建数据库连接,修改autocommit=false,执行sql

传播机制基于数据库连接,这句话很重要!一个数据库连接一个事务

流程图

事务同步器TransactionSynchronization

这个很重要,嘎嘎重要,虽然凭良心说本身呢没做什么事,extends Flushable

这个同步器有个配置transactionSynchronization:

public static final int SYNCHRONIZATION_ALWAYS = 0;//默认,同步始终生效
public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1;//事务同步仅在非 空 事务的时候生效
public static final int SYNCHRONIZATION_NEVER = 2;//从不生效

空事务:

   PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER事务传播级别 不处于事务中,无所谓commit和rollback

public interface TransactionSynchronization extends Flushable {
     //描述事务当前状态
	int STATUS_COMMITTED = 0;
	int STATUS_ROLLED_BACK = 1;
	int STATUS_UNKNOWN = 2;
 
    //挂起该事务同步器
	default void suspend() {}
    //恢复事务同步器
	default void resume() {}
    //flush 底层的session到数据库
	@Override
	default void flush() {}
    //事务提交前的回调
	default void beforeCommit(boolean readOnly) {}
    //事务commit/rollback前的回调,用于在事务完成前进行资源清除
	default void beforeCompletion() {}
 
    //事务提交后的回调,可以用于在事务成功提交后做的进一步的操作,例如:在数据提交到数据库中后,发送确认的短信或邮件
	default void afterCommit() {}
    //在事务commit/rollback之后进行回调,例如可以在事务完成后做一些资源清除
	default void afterCompletion(int status) {}
}

注册:

先注册才能用

public static void registerSynchronization(TransactionSynchronization synchronization)
      throws IllegalStateException {
 
   Assert.notNull(synchronization, "TransactionSynchronization must not be null");
   Set<TransactionSynchronization> synchs = synchronizations.get();
   if (synchs == null) {
      throw new IllegalStateException("Transaction synchronization is not active");
   }
   synchs.add(synchronization);
}

但是这个set是什么?这就需要从startTransaction开始说起了

/**
* 开启事务
*
* definition 事务属性定义对象
* transaction 事务对象
* suspendedResource 被挂起事务的资源对象,如果当前线程不存在事务 该参数对象null
*
**/
private TransactionStatus startTransaction(TransactionDefinition definition,Object transaction,boolean debugEnabled,@Nullable SuspendedResouceHolder suspendedResources){
  //只要事务同步模式 不等于 synchronization_never 事务同步在事务开启事务后生效
  boolean newSynchronization =(getTransactionSynchronization)!=SYNCHRONIZATION_NEVER);
  //创建一个事务状态对象,newTransaction
  DefaultTransactionStatus status = newTransactionStatus(definition,transaction,true,newSynchronization,debugEnable,suspendedResource);
  doBegin(transaction,definition);
  //事务同步器绑定到当前线程上下文
  prepareSynchronization(staus,definition);
  return status;
}

/**初始化事务同步器**/
protected void prepareSynchronization(DefaultTransactionStatus status,TransactionDefinition definition){
  if(status.isNewSynchronization()){

   TransactionSynchronizationManager.setAutoalTransactionActive(
status.hasTransaction());
    //记录事务隔离级别到线程上下文   
    TransactionSynchronizationManager.
setCurrentTransactionIsolationLevel(
definition.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT?definition.getIsolationLevel():null);
   //读写模式   
   TransactionSynchronizationManager
.setCurrentTransactionReadOnly(definition.isReadOnly());
   //名称
   TransactionSynchronizationManager
.setCurrentTransactionName(definition.getName());
  //激活事务同步器
  TransactionSynchronizationManager.initSynchronization();
  }
}

/**当前线程上下文激活事务同步功能,开启事务的时候会调用*/
public static void initSynchronization() throws IllegalStateException{
  if(isSynchronizationActive()){
    throw new IllegalStateException("Cannot activate transaction synchronization - already active");
  }
  logger.trace("initializing transaction synchronization");
  synchronizations.set(new LinkedHashSet<>());
}

     小结:仔细的朋友知道了吧,每次创建新spring事务调用startTransation prepareSynchronization 将事务信息放到上下文,initSynchronization初始化空set到synchronizations中! 完美

补充一个细节newTransactionStatus:

     把SuppendedResourcesHolder放到DefaultTransactionStatus中,当前上下文创建的是新事务,原事务缓存到TransactionStatus对象中;

protected DefaultTransactionStatus newTransactionStatus(
      TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
      boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
 
   boolean actualNewSynchronization = newSynchronization &&
         !TransactionSynchronizationManager.isSynchronizationActive();
   return new DefaultTransactionStatus(
         transaction, newTransaction, actualNewSynchronization,
         definition.isReadOnly(), debug, suspendedResources);
}

具体怎么处理的,请见下回 算了……一起说了吧 

private TransactionStatus handleExistingTransaction(
    TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
 
        //判断不同的事务传播级别
        //PROPAGATION_REQUIRES_NEW开启一个新的事务
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction, creating new transaction with name [" +
                        definition.getName() + "]");
            }
 
            //把原来的事务挂起,remove解绑ThreadLocal中与当前线程上下文绑定的资源对象,
            //SuspendedResourcesHolder中缓存原事务资源对象
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
            try {
                //创建一个新的事务
                return startTransaction(definition, transaction, debugEnabled, suspendedResources);
            } catch (RuntimeException | Error beginEx) {
                resumeAfterBeginException(transaction, suspendedResources, beginEx);
                throw beginEx;
            }
        }
 
    // ...............
}

分开写吧,显得少点

protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {

if (TransactionSynchronizationManager.isSynchronizationActive()) {
    //说明当前线程上下文中存在事务
    //回调线程上下文中所有事务同步器,并执行suspend,再把所有事务同步器从线程上下文中移除
    List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
    try {
        //被挂起的资源
        Object suspendedResources = null;
        if (transaction != null) {
            suspendedResources = doSuspend(transaction);
        }
 
        //需要挂起当前的事务,所以先缓存当前上下文中的事务,等事务恢复再从缓存中获取,注意后面会把新事务信息放到线程上下文
        //获取被挂起的事务名称
        String name = TransactionSynchronizationManager.getCurrentTransactionName();
        //把线程上下文中的事务名称=null
      TransactionSynchronizationManager.setCurrentTransactionName(null);
 
        //获取被挂起事务的读写模式
        boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
        //线程上下文中的事务读写=非只读    TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
 
        //获取被挂起的事务隔离级别
        Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
        //线程上下文中的事务中的事务隔离级别=null      TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
 
        //被挂起事务的激活状态
        boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
        //线程上下文中的事务激活状态=false       TransactionSynchronizationManager.setActualTransactionActive(false);
 
        // 返回被挂起的资源
        return new SuspendedResourcesHolder(
            suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
    } catch (RuntimeException | Error ex) {
        // doSuspend failed - original transaction is still active...
        doResumeSynchronization(suspendedSynchronizations);
        throw ex;
    }
}else if (transaction != null) {
    //此时线程上下文中还不存在事务
    //挂起事务资源,子类实现,返回原事务的连接对象
    Object suspendedResources = doSuspend(transaction);
    //原资源缓存在SuspendedResourcesHolder挂起资源对象中
    return new SuspendedResourcesHolder(suspendedResources);
} else {
    // Neither transaction nor synchronization active.
    return null;
}
}

   上面这个方法简单来说就是 执行doSuspend 更换线程上下文中的资源对象,将当前的资源对象放到SuspendedResourcesHolder中 

private List<TransactionSynchronization> doSuspendSynchronization() {
   //获取线程上下文中所有事务同步器
   List<TransactionSynchronization> suspendedSynchronizations =
         TransactionSynchronizationManager.getSynchronizations();
   //遍历所有的事务同步器
   for (TransactionSynchronization synchronization : suspendedSynchronizations) {
      synchronization.suspend();
   }
 
   //所有的事务同步器从线程上下文移除
   TransactionSynchronizationManager.clearSynchronization();
   return suspendedSynchronizations;
}

直接跳到提交:

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
   try {
     //事务提交
   } finally {
      //恢复被挂起事务
      cleanupAfterCompletion(status);
   }
}

/**
 * 当事务完成后会调用,进行一些清理以及恢复操作
 *
 * @param status 事务状态对象
 * @see #doCleanupAfterCompletion
 */
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
   //事务状态=已完成
   status.setCompleted();
   if (status.isNewSynchronization()) {
      //清空当前线程上下文与该事务相关信息
      TransactionSynchronizationManager.clear();
   }
 
   if (status.isNewTransaction()) {
      // 钩子方法 子类实现
      doCleanupAfterCompletion(status.getTransaction());
   }
   
   if (status.getSuspendedResources() != null) {
      //该事务中有被挂起的事务
      if (status.isDebug()) {
         logger.debug("Resuming suspended transaction after completion of inner transaction");
      }
      Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
      //恢复被挂起的事务:被挂起的事务重新绑定到当前线程上下文中
      resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
   }
}

SuspendedResourcesHolder存在说明有被挂起的事务,恢复事务 :

/**
 * 恢复指定的事务
 *
 * @param transaction     当前线程上下文的事务对象
 * @param resourcesHolder 要恢复的事务
 * @see #doResume
 * @see #suspend
 */
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
      throws TransactionException {
 
   if (resourcesHolder != null) {
      //被挂起的资源
      Object suspendedResources = resourcesHolder.suspendedResources;
      
      if (suspendedResources != null) {
         //事务恢复逻辑,由子类实现
         doResume(transaction, suspendedResources);
      }
 
      //被挂起的事务的信息放到当前线程上下文中
      List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
      if (suspendedSynchronizations != null) {
         TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
         TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
         TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
         TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
         doResumeSynchronization(suspendedSynchronizations);
      }
   }
}

当被挂起的事务提交或回滚,从线程上下文中获取它的事务同步器然后进行相应的方法回调

多数据源

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值