Spring声明式事务管理源码解读之事务提交
时间:2011-03-29 javaeye 张荣华
在下面的文章中,我讲会多次提到第一篇文章,第一篇文章是:Spring声明式事务管 理源码解读之事务开始
如果要理解事务提交的话,理解事务开始是一个前提条件,所以请先看第一篇文章,再 来看这篇
如果你仔细看下去,我想肯定是有很多收获,因为我们确实能从spring的代码和思想 中学到很多东西。
正文:
其实俺的感觉就是事务提交要比事务开始复杂,看事务是否提交我们还是要回到 TransactionInterceptor类的invoke方法
Java代码
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be <code>null</code>.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface
Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;
// Create transaction if necessary.
TransactionInfo txInfo = createTransactionIfNecessary (invocation.getMethod(), targetClass);
Object retVal = null;
try {
// This is an around advice.
// Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceed();
}
catch (Throwable ex) {
// target invocation exception
doCloseTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
doFinally(txInfo);//业务方法出栈后必须先执行的一个方法
}
doCommitTransactionAfterReturning(txInfo);
return retVal;
}
其中的doFinally(txInfo)那一行很重要,也就是说不管如何,这个doFinally方法都 是要被调用的,为什么它这么重要呢,举个例子:
我们还是以propregation_required来举例子吧,假设情况是这样的,AService中有一 个方法调用了BService中的,这两个方法都处在事务体之中,他们的传播途径都是 required。那么调用开始了,AService的方法首先入方法栈,并创建了TransactionInfo 的实例,接着BService的方法入栈,又创建了一个TransactionInfo的实例,而重点要说 明的是TransactionInfo是一个自身关联的内部类,第二个方法入栈时,会给新创建的 TransactionInfo的实例设置一个属性,就是TransactionInfo对象中的private TransactionInfo oldTransactionInfo;属性,这个属性表明BService方法的创建的 TransactionInfo对象是有一个old的transactionInfo对象的,这个oldTransactionInfo 对象就是AService方法入栈时创建的TransactionInfo对象,我们还记得在 createTransactionIfNecessary方法里有这样一个方法吧:
Java代码
protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
// We always bind the TransactionInfo to the thread, even if we didn''t create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
txInfo.bindToThread();
return txInfo;
}
就是这个bindToThread()方法在作怪:
private void bindToThread() {
// Ex
|