使用動態代理實現事務管理
阿新 • • 發佈:2019-02-11
最近在寫一個簡單的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); } }