在应用系统中,我们往往需要对数据和事务进行存取和处理,为了分离数据存取和业务逻辑我们引入了dao,但在dao中处理事务也是一件重复无聊的工作,那么我们可以采用现有的容器管理的事务如EJB和Spring ,我个人比较喜欢Spring,但是如果我们不想采用这些容器那怎么办呢.
我在这里实现了一个简单的动态事务代理类,它可以代理dao接口中声明的方法 ,通过它来创建dao的代理,我们就可以在dao中只关注数据的存取,事务由代理控制.事务处理类如下:
/**
* Author: crazy_rain
* Date: 2007-2-6
* Time: 上午09:13:35
* Introduction:事务处理类
*/
public final class TXHandler implements InvocationHandler,MethodInterceptor{
private static final Log log = LogFactory.getLog(TXHandler.class);
private ThreadLocal<Object> target = new ThreadLocal<Object>();
private static TXHandler instance;
private TXHandler(){}
/**
* 获取该类的一个实例
* @return TXHandler
*/
public static synchronized TXHandler getInstance(){
if(null == instance){
instance = new TXHandler();
}
return instance;
}
/**
* 为给定的对象实现的接口中的方法增强事务,只能增强目标实现的接口中的方法
* @param dest 需要增强事务的对象
* @return dest的代理类,实现对事务的处理
*/
public Object enhanceTransaction(Object dest){
if(dest.getClass().getInterfaces().length < 1){
throw new RuntimeException("只能增强实现接口的类...");
}
Object tar = target.get();
if(null == tar || dest != tar){
target.set(dest);
}
Object proxy = Proxy.newProxyInstance(
dest.getClass().getClassLoader(),
dest.getClass().getInterfaces(),
this);
return proxy;
}
/**
* 被代理实例所有实现的接口方法的调用都会被分派到这里执行
* @param proxy 代理类的实例
* @praam method 被代理实例实现的接口中的方法定义
* @param args 方法调用入参
* @return 方法返回值
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
//调用的方法名称
String methodName = method.getName();
Session currentSession = DaoHelper.getSession();
Transaction tx = DaoHelper.getSession().getTransaction();
try{
tx.begin();
result = method.invoke(target.get(), args);
tx.commit();
}catch(Exception ex){
log.error("调用方法: " + methodName + " 发生[" + ex.getMessage() + "]异常,事务回滚...",ex);
tx.rollback();
throw new RuntimeException(ex);
}finally{
//善后处理,如果session没有关闭则关闭
if(currentSession.isOpen()){
currentSession.close();
}
}
return result;
}
/**
* 方法拦截器,当调用被增强类的实例方法时会转向此处执行
* @param object 被代理类的实例
* @param method 被代理类的方法
* @param args 调用方法所需参数
* @param methodProxy 代理方法
*/
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result;
String methodName = method.getName();
Transaction tx = DaoHelper.getSession().getTransaction();
try {
tx.begin();
result = methodProxy.invokeSuper(object, args);
tx.commit();
} catch (Exception ex) {
tx.rollback();
log.error("调用方法: " + methodName + " 发生[" + ex.getMessage() + "]异常,事务回滚...",ex);
throw new RuntimeException(ex);
}
return result;
}
/**
* 对目标类进行事务增强
* @param dest 目标类
* @return 目标类的一个子类实例,该实例代理事务处理
*/
public Object enhanceTransaction(Class dest) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(dest);
enhancer.setCallback(this);
return enhancer.create();
}
}
该类处理了事务和异常,dao中只需处理数据存取即可.当然上述类中还有不足,希望大家指点,共同进步.