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"); }