动态代理实现横切——封装事务

原创 2015年07月27日 22:17:09

    上节课中,通过现象2可知道:如果对各个实现相同的控制,则需要重复写大量的代码。比如说,写日志,事务的开启,关闭,回滚等一系列操作。

    但是在开发的过程中,如果经常注意以上的开发,那开发效率将很低的。而且还容易出错。

    面对上面的问题,如果只是面向对象的编程。那开发的时候,程序员不仅要专注于业务逻辑的Coding,而且还要在后面写上日志的处理办法,事务的开启关闭等一系列与业务逻辑无关的代码。log.write(class,operate)……

效率上肯定是要打折扣的。而且,把这种重复性的工作交给人力。是非常的容易出现问题的。

 

    现在,要想提高效率。重复的工作交给机器。程序员专心Coding业务逻辑。

 

面向切面的编程,可以解决这种问题。

 

前提:事务的控制,发生在B层,dal层是对数据的访问。而业务逻辑的整合在B层。所以需要对B层中的方法,都加上事务。

   

    取得B层实现,是通过工厂取得。

用动态代理封装事务:

package com.bjpowernode.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;

/**
 * 采用动态代理封装事务
 */
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 (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;
	}

}

 

    通过上面的方法,可以对B层的对象 进行一个包装的过程,使得对  add 、del、modify开头的方法。包装上一层事务的 开启  提交 回滚等一系列操作。

 

获取B层实现的方法:

/**
	 * 根据产品编号取得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");
//		System.out.println(className);
		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) {
			e.printStackTrace();
			throw new RuntimeException("创建Service失败!");
		}
		return service;
	}


    在获取B层对象实例的时候, 进行包装事务。

 

    通过上面getServiceObject获取得到的B层对象,在调用增删改操作的时候,都会有事务控制。这样程序员在开发的过程中就可以专心的开发业务逻辑。而不用思考什时候需要开启事务,什么情况需要提交,什么时候需要回滚等一系列与业务逻辑无关的操作。

 

    在此之前,一直以为实现面向切面的编程需要使用Spring.AOP  通过学习的深入,才发现,面向切面的编程是一种思想,不管用什么技术实现。

    面向对象的编程加上面向切面的编程。才会让编程更加有乐趣,更加有效率。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java事务处理全解析(六)—— 使用动态代理(Dynamic Proxy)完成事务

在本系列的上一篇文章中,我们讲到了使用Template模式进行事务管理,这固然是一种很好的方法,但是不那么完美的地方在于我们依然需要在service层中编写和事务处理相关的代码,即我们需要在servi...

JAVA动态代理用法与实现过程

jdk动态代理实现已即原理

使用INDY的IdMappedPortTCP控件实现动态的HTTP代理服务器

作者 : lxm365 标题 : 使用INDY的IdMappedPortTCP控件实现动态的HT...

JAVA动态代理用法与实现过程

jdk动态代理实现已即原理

SpringAOP(二) 利用动态代理实现横切逻辑

原始的性能监控功能中性能监控的代码和业务层代码混合在一起,当某个方法需要进行性能监控,就必须调整方法代码,在方法的前面后面加上性能监控代码,这些非业务逻辑的性能监控代码破坏了业务逻辑的纯粹性。    ...

代理模式深入学习(二)——实现动态代理对事务的封装

前两篇博客已经为这篇博客做了很多铺垫,从动态代理的实现衍生原理到threadLocal来封装事务,到最后真正的利用动态代理来封装事务。缺少每一 步都似乎显得有些冒进了!现在剩下的就只是把先前封...

Java事务(6)——使用动态代理(Dynamic Proxy)

在本系列的上一篇文章中,我们讲到了使用Template模式进行事务管理,这固然是一种很好的方法,但是不那么完美的地方在于我们依然需要在service层中编写和事务处理相关的代码,即我们需要在servi...

TransactionHandler类,描述封装事务和connection的动态代理类的类,目标类是manager实现类,提供事务的功能

package com.bjpowernode.drp.util; import java.lang.reflect.InvocationHandler; import java.lang.r...

Java事务之六——使用动态代理(Dynamic Proxy)

Java事务之六——使用动态代理(Dynamic Proxy) 本文转载自:http://www.cnblogs.com/davenkin/archive/2013/02/24/java-tra...

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

如果采用三层架构的方式开发,在业务逻辑层不可避免的要手动操作事务,所以在业务逻辑层会出现很多与业务逻辑无关的: Connection conn = ConnectionManage.GetConne...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:动态代理实现横切——封装事务
举报原因:
原因补充:

(最多只允许输入30个字)