如果采用三层架构的方式开发,在业务逻辑层不可避免的要手动操作事务,所以在业务逻辑层会出现很多与业务逻辑无关的:
Connection conn = ConnectionManage.GetConnection();
ConnectionManage.beginTransaction(conn);ConnectionManage.commitTransaction(conn);等等代码。
不仅不合理,而且是重复劳动,程序开发的一个原则就是杜绝重复劳动,做到良好的封装。
这里,我们就采用动态代理对事务进行封装,使我们的业务逻辑层不再出现有关事务的代码。
package com.jialin.drp.util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
/**
* 使用动态代理封装事务
* @author jialin
*
*/
public class TransactionHandler implements InvocationHandler {
private Object targetObject;
/**
* 获取目标类的代理
* @param targetObject
* @return
*/
public Object newProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
/**
* 代理方法,调用目标类方法前先调用该方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Connection conn = null;
Object ret = null;
try {
// 从ThreadLocal中取得Connection。ConnectionManage是对connection的封装
conn = ConnectionManage.GetConnection();
//如果是以add,del,modify开头的方法,则手动开启事务
if (method.getName().startsWith("add")
|| method.getName().startsWith("del")
|| method.getName().startsWith("modify")) {
// 手动控制事务提交
ConnectionManage.beginTransaction(conn);
}
// 调用目标对象的业务逻辑方法
ret = method.invoke(targetObject, args);
//如果事务为手动提交方式,则手动提交事务
if (!conn.getAutoCommit()) {
// 提交事务
ConnectionManage.commitTransaction(conn);
}
} catch (Exception e) {
//如果事务为手动提交方式,则手动回滚事务
if (!conn.getAutoCommit()) {
// 回滚事务
ConnectionManage.rollbackTransaction(conn);
}
e.printStackTrace();
if (e instanceof InvocationTargetException) {
InvocationTargetException ete = (InvocationTargetException) e;
throw ete.getTargetException();
}
throw new Exception("操作失败!");
} finally {
//关闭连接
ConnectionManage.closeConnection();
}
return ret;
}
}
原理:当我们在工厂中获取业务逻辑层对象的时候,我们获取的并不是目标对象,而是目标对象的代理,代理替我们管理事务的开启,提交,回滚,与关闭
在工厂中用动态代理包装业务逻辑对象
public synchronized Object GetServiceBean(Class c) {
if (ServiceMap.containsKey(c.getName())) {
return ServiceMap.get(c.getName());
}
Element beanEle = (Element) doc.selectSingleNode("//Service[@id=\""
+ c.getName() + "\"]");
String className = beanEle.attributeValue("class");
// System.out.print(className);
Object serviceBean = null;
try {
serviceBean = Class.forName(className).newInstance();
//采用动态代理包装Service
TransactionHandler transactionHandler = new TransactionHandler();
//得到代理
serviceBean = transactionHandler.newProxyInstance(serviceBean);
ServiceMap.put(c.getName(), serviceBean);
} catch (Exception e) {
throw new RuntimeException();
}
return serviceBean;
}
//获取的并不是目标对象,而是目标对象的代理
userManager = (UserManager) getBeanFactory().GetServiceBean(UserManager.class);