动态代理封装时事务
结合上篇博客《动态代理模式》,我们来使用它来封装一下事务管理,记得以前使用事务,对管理的抽象也仅限于抽离出一个类,通过传入数据库连接,对事务进行开启、提交、回滚等操作,每一个。但是仔细想想我们的业务流程是固定的,哪里使用或不使用事务也是固定的,所以,事务和业务之间并非必须的耦合关系,以下就是通过动态代理将业务和事务解耦。
代理类
TransactionHandler,这个是对事务操作的核心,将需要事务的函数在此处理:
[java] view plaincopyprint?
- 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 Administrator
- *
- */
- public class TransactionHandler implements InvocationHandler {
- private Object targetObject;
- public Object newProxyInstance(Object targetObject) {
- this.targetObject = targetObject;
- return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(), this);
- }
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- Connection conn = null;
- Object ret = null;
- try {
- //从ThreadLocal中取得Connection
- conn = ConnectionManager.getConnection();
- if (method.getName().startsWith(“add”) ||
- method.getName().startsWith(“del”) ||
- method.getName().startsWith(“modify”)) {
- //手动控制事务提交
- ConnectionManager.beginTransaction(conn);
- }
- //调用目标对象的业务逻辑方法
- ret = method.invoke(targetObject, args);
- if (!conn.getAutoCommit()) {
- //提交事务
- ConnectionManager.commitTransaction(conn);
- }
- }catch(ApplicationException e) {
- //回滚事务
- ConnectionManager.rollbackTransaction(conn);
- throw e;
- }catch(Exception e) {
- e.printStackTrace();
- if (e instanceof InvocationTargetException) {
- InvocationTargetException ete = (InvocationTargetException)e;
- throw ete.getTargetException();
- }
- //回滚事务
- ConnectionManager.rollbackTransaction(conn);
- throw new ApplicationException(“操作失败!”);
- }finally {
- ConnectionManager.closeConnection();
- }
- return ret;
- }
- }
使用封装的事务
在工厂中创建Service实例时,使用封装的事务。
[java] view plaincopyprint?
- /**
- * 根据产品编号取得Service系列产品
- * @param beanId
- * @return
- */
- public synchronized Object getServiceObject(Class c){
- //如果存在相关对象实例,返回
- if (serviceMap.containsKey(c.getName())) {
- return serviceMap.get(c.getName());
- }
- Element beanElt = (Element)doc.selectSingleNode(“//service[@id=\”” + c.getName() + “\”]”);
- String className = beanElt.attributeValue(“class”);
- Object service = null;
- try {
- service = Class.forName(className).newInstance();
- //采用动态代理包装Service
- TransactionHandler transactionHandler = new TransactionHandler();
- service = transactionHandler.newProxyInstance(service);
- //将创建好的对象放到Map中
- serviceMap.put(c.getName(), service);
- } catch (Exception e) {
- throw new RuntimeException();
- }
- return service;
- }
在这里我们需要注意的是,当代理类截获异常后,会对异常进行封装,封装为InvocationTargetException,所以如果要对原异常进行处理,需要对异常进行类型判断再行处理。