分类: Java
2008-01-18 14:24:05
<----- 接2续 ----->
上次说到spring声明式事务管理的事务开始部分,按流程来讲,下面应该提交事务了, spring的声明式事务管理其实是比较复杂的,事实上这种复杂性正是由于事务本身的复杂性导致的,如果能用两三句话就把这部分内容说清楚是不现实的,也是不成熟的,而我对这部分的理解也可能是不全面的,还是那句话,希望大家和我一起把本贴的质量提交起来。在下面的文章中,我讲会多次提到第一篇文章,第一篇文章的地址是:
如果要理解事务提交的话,理解事务开始是一个前提条件,所以请先看第一篇文章,再来看这篇 如果你仔细看下去,我想肯定是有很多收获,因为我们确实能从spring的代码和思想中学到很多东西。
正文:
其实俺的感觉就是事务提交要比事务开始复杂,看事务是否提交我们还是要回到TransactionInterceptor类的invoke方法。
代码
1. public Object invoke(MethodInvocation invocation) throws Throwable {
2. // Work out the target class: may be null
.
3. // The TransactionAttributeSource should be passed the target class
4. // as well as the method, which may be from an interface
5. Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;
6.
7. // Create transaction if necessary.
8. TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);
9.
10. Object retVal = null;
11. try {
12. // This is an around advice.
13. // Invoke the next interceptor in the chain.
14. // This will normally result in a target object being invoked.
15. retVal = invocation.proceed();
16. }
17. catch (Throwable ex) {
18. // target invocation exception
19. doCloseTransactionAfterThrowing(txInfo, ex);
20. throw ex;
21. }
22. finally {
23. doFinally(txInfo);//业务方法出栈后必须先执行的一个方法
24. }
25. doCommitTransactionAfterReturning(txInfo);
26. return retVal;
27. }
其中的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方法里有这样一个方法吧:
代码
1. protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
2. // We always bind the TransactionInfo to the thread, even if we didn't create
3. // a new transaction here. This guarantees that the TransactionInfo stack
4. // will be managed correctly even if no transaction was created by this aspect.
5. txInfo.bindToThread();
6. return txInfo;
7. }
就是这个bindToThread()方法在作怪:
1. private void bindToThread() {
2. // Expose current TransactionStatus, preserving any existing transactionStatus for
3. // restoration after this transaction is complete.
4. oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get();
5. currentTransactionInfo.set(this);
6. }
如果当前线程中已经有了一个TransactionInfo,则拿出来放到新建的transactionInfo对象的oldTransactionInfo属性中,然后再把新建的TransactionInfo设置到当前线程中。
这里有一个概念要搞清楚,就是TransactionInfo对象并不是表明事务状态的对象,表明事务状态的对象是TransactionStatus对象,这个对象同样是TransactionInfo的一个属性(这一点,我在前面一篇文章中并没有讲清楚)。
接下来BService中的那个方法返回,那么该它退栈了,它退栈后要做的就是doFinally方法,即把它的oldTransactionInfo设置到当前线程中(这个TransactionInfo对象显然就是AService方法入栈时创建的,怎么现在又要设置到线程中去呢,原因就是BService的方法出栈时并不提交事务,因为BService的传播途径是required,所以要把栈顶的方法所创建transactioninfo给设置到当前线程中),即调用AService的方法时所创建的TransactionInfo对象。那么在AServie的方法出栈时同样会设置TransactionInfo对象的oldTransactionInfo到当前线程,这时候显然oldTransactionInfo是空的,但AService中的方法会提交事务,所以它的oldTransactionInfo也应该是空了。
在这个小插曲之后,么接下来就应该是到提交事务了,之前在AService的方法出栈时,我们拿到了它入栈时创建的TransactionInfo对象,这个对象中包含了AService的方法事务状态。即TransactionStatus对象,很显然,太显然了,事务提交中的任何属性都和事务开始时的创建的对象息息相关,这个TransactionStatus对象哪里来的,我们再回头看看createTransactionIfNessary方法吧:
代码
1. protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
2. txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));
3. }
再看看transactionManager.getTransaction(txAttr)方法吧:
代码
1. public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
2. ………………………..
3. else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
4. definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
5. definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
6. if (debugEnabled) {
7. logger.debug("Creating new transaction with name [" + definition.getName() + "]");
8. }
9. doBegin(transaction, definition);
10. boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
11. return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);//注意这里的返回值,返回的就是一个TransactionStatus对象,这个对象表明了一个事务的状态,比如说是否是一个新的事务,事务是否已经结束,等等,这个对象是非常重要的,在事务提交的时候还是会用到它的。
12. }
13. }
<------ 未完 ------>