使用动态代理实现事务管理

最近在写一个简单的web框架,使用动态代理和ThreadLocal实现的事务管理,在这里和大家分享一下。

关于动态代理有jdk动态代理和cglib动态代理,这里选用了cglib。

DbHelper类提供数据库的一些操作。

package com.me.coin.framework.dao;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

/**
 * 提供数据库的一些操作
 * @author dwl
 *
 */
public class DbHelper {
        
        //线程变量
	private static ThreadLocal localConn = new ThreadLocal();
        //数据库连接池
	private static DataSource dataSource = DataSourceMaker.getInstance().getDataSource();

	
	/**
	 * 获取连接
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn;
		try {
			conn = localConn.get();
			if (conn == null) {
				conn = dataSource.getConnection();
				if (conn != null) {
					localConn.set(conn);
				}
			}
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
		return conn;
	}

	
	/**
	 * 开启事务
	 */
	public static void beginTransaction() {
		Connection conn = getConnection();
		if (conn != null) {
			try {
				conn.setAutoCommit(false);
			} catch (SQLException e) {
				throw new RuntimeException(e);
			} finally {
				localConn.set(conn);
			}
		}
	}

	/**
	 * 提交事务
	 */
	public static void commitTransaction() {
		Connection conn = getConnection();
		if (conn != null) {
			try {
				conn.commit();
				conn.close();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			} finally {
				localConn.remove();
			}
		}
	}

	/**
	 * 回滚事务
	 */
	public static void rollbackTransaction() {
		Connection conn = getConnection();
		if (conn != null) {
			try {
				conn.rollback();
				conn.close();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			} finally {
				localConn.remove();
			}
		}
	}

}

TransactionProxy类获取代理后的对象

package com.me.coin.framework.tx;

import java.lang.reflect.Method;

import com.me.coin.framework.dao.DbHelper;
import com.me.coin.framework.tx.annotation.Transaction;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 事务代理
 * @author dwl
 *
 */
public class TransactionProxy {
	
	@SuppressWarnings({ "unchecked", "static-access" })
	public static  T getProxy(Class clazz){
		return (T)new Enhancer().create(clazz, new MethodInterceptor(){
			@Override
			public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
				Object result = null;
				//没有@Transaction不进行事务管理
				if(!method.isAnnotationPresent(Transaction.class)){
					result = proxy.invokeSuper(obj, args);
					return result;
				}
				try {
					//开启事务
					DbHelper.beginTransaction();
					// 通过代理类调用父类中的方法
					result = proxy.invokeSuper(obj, args);
					//提交事务
					DbHelper.commitTransaction();
				} catch (Exception e) {
					//回滚
					DbHelper.rollbackTransaction();
				}
				return result;
			}
		});
	}

}

 在ioc初始化时获取所有需要事务管理的service类

//service类通过动态代理生成
Object bean = TransactionProxy.getProxy(clazz);
		

在service层进行事务管理

package com.dwl.controller;

import java.util.List;

import com.dwl.entity.User;
import com.me.coin.framework.dao.Cnd;
import com.me.coin.framework.dao.Dao;
import com.me.coin.framework.ioc.annotation.Inject;
import com.me.coin.framework.tx.annotation.Service;
import com.me.coin.framework.tx.annotation.Transaction;

@Service//标识service类
public class UserServiceImpl implements UserService{
	
	@Inject//注入
	private Dao dao;

	@Override
	public List getList(Cnd cnd) {
		return dao.query(User.class, cnd);
	}

	@Override
	@Transaction//事务管理,不支持事务传播
	public long addUser(User user) {
	    return dao.insert(user);
	}

}

详细代码访问github:https://github.com/daiwenlong/coin-framework

你可能感兴趣的:(动态代理)