日期:2014-05-19 浏览次数:20571 次
package cn.tsb.comm.db.transaction;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.EmptyStackException;
import java.util.Stack;
import javax.transaction.UserTransaction;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.log4j.Logger;
/*
* Copyright (C) 2012 TSB
* All Rights Reserved
* Description: 方法拦截,事务管理
*
* Modification History:
**********************************************************
* Date Author Comments
**********************************************************
* 2012/9/19 Init Version
*/
public abstract class TransactionProxy implements MethodInterceptor {
private static Logger log = Logger.getLogger(TransactionProxy.class);
private String ERROR = TMConstants.ERROR+Thread.currentThread().getId()+" | ";
private String DEBUG = TMConstants.DEBUG+Thread.currentThread().getId()+" | ";
//执行堆,以此实现事务的原子性,为空是进入事务开始,再次为空时事务结束
private static final ThreadLocal<Stack<String>> threadLocal = new ThreadLocal<Stack<String>>();
private String methodname = "";
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
methodname = method.getName();
Object ret = null;
if(method.getName().equals("finalize") || method.getName().equals("count")){
ret = proxy.invokeSuper(obj, args);
}else{
try {
// for each new invoke, push stack
if (isEmpty()) {
//begin();
//本来这里应该ut.begin()的。但为了保证事务的开始在获取连接(第一个)之后,所以这里只打印日志。
//有一种情况会出现:假设一个业务方法需要两个连接,第一个连接打开之后,第二个连接打开之前,会ut.begin,不知道是不是这个原因
preBegin();
}
push(method.getName());
//log.debug(DEBUG+"method="+method.getName()+" os="+(threadLocal.get()==null?"0":threadLocal.get().size())+" ts="+(transactionLocal.get()==null?"0":transactionLocal.get().size())+" cs="+(connLocal.get()==null?"0":connLocal.get().size()));
ret = proxy.invokeSuper(obj, args); // do business
// finish once, pop up
methodname = pop();
// check whether commit the transaction
if (isEmpty()) {
commit();
//提交
}
} catch (Throwable e) {
// if it is in the inner of the invoke chain, throw exception
// directly.
methodname = pop();
if (isEmpty()) {
rollback(