`
thecloud
  • 浏览: 880676 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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

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


分享到:
评论

相关推荐

    idc网管系统

    本项目结 构上分为表现层、业务层和数据访问层,层次间的依赖关系自下到上。采用的技术有Struts,Spring,Hibernate,Log4J,JDom 等。其中表现层采用Struts框架开发;...为提高性能,采用Servlet Filter实现了缓存代理

    计算机软件项目设计方案(2020).docx

    技术实现事务管理、服务日志、统一异常处理,在远程服务调用中使用RPC Context实现上下文管理,持久化框架采用Hibernate、Mybatis双框架兼容设计,使用数据访问代理服务,实现分库分表环境下的透明数据访问。...

    网站设计方案(完整版).doc

    对其中……这类业务相关性的动态数据,这类数据来源可以是来自于信息系统,也可以 采用填报功能,数据设计存储在物理表中,一是把发布和数据来源管理分离,二是更加 方便地进行权限控制。 从数据安全角度考虑,考虑...

    TCP-IP详解.卷三:TCP事务协议,HTTP,NNTP和UNIX域协议

    24.7 T/TCP:为事务用的TCP扩展 265 24.8 TCP的性能 267 24.9 小结 268 第25章 SNMP:简单网络管理协议 270 25.1 引言 270 25.2 协议 270 25.3 管理信息结构 272 25.4 对象标识符 274 25.5 管理信息库介绍 274 25.6 ...

    java开源包4

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    lamp-cloud微服务脚手架

    将服务保留的rest进行代理和网关控制,除了平常经常使用的node.js、nginx外,Spring Cloud系列的zuul和ribbon,可以帮我们进行正常的网关管控和负载均衡。其中扩展和借鉴国外项目的扩展基于JWT的Zuul限流插件,方面...

    java面试题

    答:声明式的事务管理主要是将在进行对数据库中数据的添加或者修改时需要执行事务管理,主要是为了避免在执行添加或修改的时候添加或修改不完全正确,导致数据丢失。spring使用AOP面向切面的思想进行事务管理的。 ...

    基于maven项目的SSM框架与layu前端框架的代码

    实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织...

    在线考试系统文献综述

    Web技术超越了传统的"客户机/服务器"两层结构,采用了三层体系结构:用户界面层/事务层/数据库层,因此Web结构有着更好的安全性,在用户机上不需要安装任何应用程序,应用程序可以安装在事务层所在的计算机上,试题...

    java开源包1

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包11

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包2

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包3

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包6

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包5

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包10

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包8

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包7

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

    java开源包9

    它采用的是 JTidy 库对HTML进行处理。 INI文件操作类库 [ini4j] [ini4j] 是一个简单的Java类库,用来读写Windows的ini配置文件。同时还包含一个 Java Perferences API 的实现。 拒绝服务测试工具 Port Groper ...

Global site tag (gtag.js) - Google Analytics