在应用系统中,我们往往需要对数据和事务进行存取和处理,为了分离数据存取和业务逻辑我们引入了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中只需处理数据存取即可.当然上述类中还有不足,希望大家指点,共同进步.