免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 830 | 回复: 0
打印 上一主题 下一主题

Spring声明式事务管理源码解读(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-18 14:16 |只看该作者 |倒序浏览

Spring声明式事务管理源码解读
/***作者:张荣华(ahuaxuan) *2007-06-16 *转载请注明出处及作者*/
出自:http://www.javaeye.com/topic/87426
简介:事务是所有企业应用系统的核心,之前人们使用ejb的时候,容器事务管理(CMT),是slsb最令人称道的地方,据说很多人使用ejb,使用slsb就是为了cmt,但是spring出现之后,格局就变了,因为程序员又多了一种选择,就是声明式事务管理,声明式事务管理是基于AOP的,及AOP是它的底层特性,本文的目的就是为了和大家探讨一下spring的声明式事务管理,从源代码来分析它的背后的思想。
这个是我昨天在解决问题是看源码得一点体验,可能说得比较大概,希望大家多多讨论,把本贴得质量提高上去,因为spring实现的事务管理这部分我相信还是有点复杂的。一个人未必能想得十分清楚,在spring的声明式事务管理中,它是如何判定一个及标记一个方法是否应该是处在事务体之中呢。
首先要理解的是spring是如何来标记一个方法是否应该处在事务体之中的。有这样一个接口TransactionDefinition,其中定义了很多常量,它还有一个子接口TransactionAttribute,其中只有一个方法rollback。
TransactionDefinition中有很多常量定义,它们分别属于两种类型,传播途径和隔离级别
代码
1.       /**  
2.        * Support a current transaction; create a new one if none exists.  
3.        * Analogous to EJB transaction attribute of the same name.  
4.        * This is typically the default setting of a transaction definition.  
5.        */  
6.       int PROPAGATION_REQUIRED = 0;  
当然其中也定义了隔离级别
代码
1.       /**  
2.        * A constant indicating that dirty reads are prevented; non-repeatable reads   
3.        * And phantom reads can occur. This level only prohibits a transaction   
4.        * From reading a row with uncommitted changes in it.   
5.        * @see java.sql.Connection#TRANSACTION_READ_COMMITTED   
6.        */   
7.       int ISOLATION_READ_COMMITTED   = Connection.TRANSACTION_READ_COMMITTED;  
同时还有两个对应的方法来得到这样的传播途径和隔离级别
代码
1.       /**
2.        * Return the propagation behavior.  
3.        * Must return one of the PROPAGATION constants.  
4.        * @see #PROPAGATION_REQUIRED  
5.        * @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()  
6.        */  
7.       int getPropagationBehavior();   
8.         
9.       /**  
10.     * Return the isolation level.  
11.     * Must return one of the ISOLATION constants.  
12.     * Only makes sense in combination with PROPAGATION_REQUIRED or  
13.     * PROPAGATION_REQUIRES_NEW.  
14.     * Note that a transaction manager that does not support custom  
15.     * isolation levels will throw an exception when given any other level  
16.     * than ISOLATION_DEFAULT.  
17.     * @see #ISOLATION_DEFAULT  
18.     */  
19.    int getIsolationLevel();  
这个接口有一个默认的实现DefaultTransactionDefinition。然后它还有子类,比如说 DefaultTransactionAttribute。Spring在判断一个方法是否需要事务体的时候其实是创建一个TransactionAttribute实现的实例.
有了上面的简单介绍就可以进入真正判断是否需要事务的地方了。这个方法在TransactionAspectSupport类里,
代码
1.       /**  
2.            * Create a transaction if necessary.  
3.            * @param method method about to execute  
4.            * @param targetClass class the method is on  
5.            * @return a TransactionInfo object, whether or not a transaction was created.  
6.            * The hasTransaction() method on TransactionInfo can be used to tell if there  
7.            * was a transaction created.  
8.            */  
9.           protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {   
10.            // If the transaction attribute is null, the method is non-transactional.   
11.            final TransactionAttribute sourceAttr =   
12.                    this.transactionAttributeSource.getTransactionAttribute(method, targetClass);//就是在这里判断了这个方法的事务属性   
13.            TransactionAttribute txAttr = sourceAttr;   
14.      
15.            // If no name specified, apply method identification as transaction name.   
16.            if (txAttr != null && txAttr.getName() == null) {   
17.                final String name = methodIdentification(method);   
18.                txAttr = new DelegatingTransactionAttribute(sourceAttr) {   
19.                    public String getName() {   
20.                        return name;   
21.                    }   
22.                };   
23.            }   
24.      
25.            TransactionInfo txInfo = new TransactionInfo(txAttr, method);   //TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性   
26.            if (txAttr != null) {   
27.                // We need a transaction for this method   
28.                if (logger.isDebugEnabled()) {   
29.                    logger.debug("Getting transaction for " + txInfo.joinpointIdentification());   
30.                }   
31.      
32.                // The transaction manager will flag an error if an incompatible tx already exists   
33.                txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));//这个方法要仔细的看   
34.            }   
35.            else {   
36.                // The TransactionInfo.hasTransaction() method will return   
37.                // false. We created it only to preserve the integrity of   
38.                // the ThreadLocal stack maintained in this class.   
39.                if (logger.isDebugEnabled())   
40.                    logger.debug("Don't need to create transaction for [" + methodIdentification(method) +   
41.                            "]: this method isn't transactional");   
42.            }   
43.      
44.            // We always bind the TransactionInfo to the thread, even if we didn't create   
45.            // a new transaction here. This guarantees that the TransactionInfo stack   
46.            // will be managed correctly even if no transaction was created by this aspect.   
47.            txInfo.bindToThread();   
48.            return txInfo;   
49.    }  

TransactionInfo是TransactionAspectSupport的一个内部类,它的主要功能是记录方法和对应的事务属性,在上面这个方法的最后,这个TransactionInfo对象被保存到当前线程中。
而这个方法会在事务拦截器TransactionInterceptor中被调用,TransactionInterceptor实际上是TransactionAspectSupport的子类,看看其中的invoke方法:

代码
1.       // Work out the target class: may be null.   
2.       // The TransactionAttributeSource should be passed the target class   
3.       // as well as the method, which may be from an interface   
4.               Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;   
5.                  
6.               // Create transaction if necessary.   
7.               TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);   
8.         
9.               Object retVal = null;   
10.            try {   
11.                // This is an around advice.   
12.                // Invoke the next interceptor in the chain.   
13.                // This will normally result in a target object being invoked.   
14.                retVal = invocation.proceed();   
15.            }   
16.            catch (Throwable ex) {   
17.                // target invocation exception   
18.                doCloseTransactionAfterThrowing(txInfo, ex);   
19.                throw ex;   
20.            }   
21.            finally {   
22.                doFinally(txInfo);   
23.            }   
24.            doCommitTransactionAfterReturning(txInfo);//在这里执行方法结束之后需要的操作   
25.            return retVal;  
这个方法就如同一般的interceptor需要实现的方法一样。只不过在这个方法里判断被反射的方法是否需要事务。





本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/12821/showart_467099.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP