最近在写一个简单的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<Connection> localConn = new ThreadLocal<Connection>();
//数据库连接池
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> T getProxy(Class<T> 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<User> 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