spring源码-事务

事务是依靠动态代理实现的

代理对象的创建

如果我们对一个目标类添加了@Transactional注解,假设目标类beanName为activityServiceImpl


@Service

publicclass ActivityServiceImplimplementsActivityService{

    @Override

    @Transactional

    public void insert() {

      new RuntimeException("activityService insert err");

     }

}


在beanFactory初始化目标bean之后,会循环所有的processor对bean进行后置处理,遇到AbstractAutoProxyCreator这个processor,

会为这个目标bean创建代理,我们暂且选择jdk动态代理,下图是生成的代理对象


很显然,生成的这个代理类实现了ActivitySerivice,继承了Proxy,持有InvocationHandler(上图中的h),这个handler是代理对象和目标对象的桥梁

这个代理对象会被存入bean工厂中,此后我们在业务类中拿到的bean就是这个代理对象了。


下面我们看看在调用insert方法的时候,发生了什么?

上图中的代理对象执行insert,会执行h.invoke,所以我们需要关注一下JdkDynamicAopProxy中的invoke方法,这个方法中的下面这行比较重要


List  chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);



ReflectiveMethodInvocation invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

retVal = invocation.proceed();


这个proceed会执行到TransactionInterceptor中的invoke(),然后执行到TransactionAspectSupport中的invokeWithinTransaction()

这个方法是关键!!!我们先看一种最简单的执行情况


TransactionAspectSupport.TransactionInfo ex =this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

Object retVal = null;

try {

    retVal =invocation.proceedWithInvocation();

} catch (Throwable var15) {

   this.completeTransactionAfterThrowing(ex, var15);

    throw var15;

} finally {

   this.cleanupTransactionInfo(ex);

}

this.commitTransactionAfterReturning(ex);


很明显,创建事务,目标对象执行业务,根据执行结果提交或者回归事务,一目了然

现在我们分析一个嵌套事务,基于本文开头的代码,我们新增一个prizeService类

@Service
public class PrizeServiceImpl implements PrizeSerivce {
    @Autowired
    ActivityService activityService;

    @Override
    @Transactional
    public int insert() {
        try {
            activityService.insert();
        } catch (Exception e) {

        }
        return 3;
    }
}
此时prizeServiceImpl调用了activityService,形成了一个嵌套事务,事务的传播属性默认为REQUIRED,spring会为两个类都生成代理对象,我们现在执行prizeServiceImpl的insert方法,调试一下源代码

程序运行到activitySerivice(代理对象)的insert(),此时先获取事务,

if(this.isExistingTransaction(transaction)) {
    return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
如果当前线程事务已经存在,传播属性为REQUIRED,将不会创建新的事务。

此时transcationInfo信息



接着执行activityService()(目标对象)的insert(),出现异常

try {
    retVal = invocation.proceedWithInvocation();
} catch (Throwable var15) {
    this.completeTransactionAfterThrowing(ex, var15);
    throw var15;
} finally {
    this.cleanupTransactionInfo(ex);
}
如上述代码,将执行completeTransactionAfterThrowing,这个方法会先判断此异常是否需要rollBack事务 

public boolean rollbackOn(Throwable ex) {
    return ex instanceof RuntimeException || ex instanceof Error;
}
显然,只有ex继承了RuntimeException或者Error,才判定为需要rollback

} else if(status.isNewTransaction()) {
    if(status.isDebug()) {
        this.logger.debug("Initiating transaction rollback");
    }

    this.doRollback(status);
} else if(status.hasTransaction()) {
    if(!status.isLocalRollbackOnly() && !this.isGlobalRollbackOnParticipationFailure()) {
        if(status.isDebug()) {
            this.logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
        }
    } else {
        if(status.isDebug()) {
            this.logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
        }

        this.doSetRollbackOnly(status);
    }
但是这个事务会不会立即回滚呢?

看上述代码只有新事务才会立即回滚,这个明显不是新的事务,它只会设置一个rollbackOnly的状态

继续执行,prizeService.insert因为try-catch(吞掉了异常未抛出),所以捕捉不到异常,会继续执行,最后提交的时候发现这个事务已被标记成rollbackOnly,此时回滚这个事务,并且抛出异常

this.processRollback(defStatus);
if(status.isNewTransaction() || this.isFailEarlyOnGlobalRollbackOnly()) {
    throw new UnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");
}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值