您的位置:首页 > 其它

采用动态代理对事务进行封装

2013-03-11 10:00 260 查看
如果采用三层架构的方式开发,在业务逻辑层不可避免的要手动操作事务,所以在业务逻辑层会出现很多与业务逻辑无关的:

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: