博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
采用动态代理对事务进行封装
阅读量:4048 次
发布时间:2019-05-25

本文共 2922 字,大约阅读时间需要 9 分钟。

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

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);

 

 

 

 

转载地址:http://yedci.baihongyu.com/

你可能感兴趣的文章
C# 托管与非托管
查看>>
Node.js中的事件驱动编程详解
查看>>
mongodb 命令
查看>>
MongoDB基本使用
查看>>
mongodb管理与安全认证
查看>>
nodejs内存控制
查看>>
nodejs Stream使用中的陷阱
查看>>
MongoDB 数据文件备份与恢复
查看>>
数据库索引介绍及使用
查看>>
MongoDB数据库插入、更新和删除操作详解
查看>>
MongoDB文档(Document)全局唯一ID的设计思路
查看>>
mongoDB简介
查看>>
Redis持久化存储(AOF与RDB两种模式)
查看>>
memcached工作原理与优化建议
查看>>
Redis与Memcached的区别
查看>>
redis sharding方案
查看>>
程序员最核心的竞争力是什么?
查看>>
Node.js机制及原理理解初步
查看>>
linux CPU个数查看
查看>>
分布式应用开发相关的面试题收集
查看>>