zoukankan      html  css  js  c++  java
  • 动态代理实现横切——封装事务

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

        可是在开发的过程中,假设常常注意以上的开发,那开发效率将非常低的。并且还easy出错。

        面对上面的问题。假设仅仅是面向对象的编程。那开发的时候。程序猿不仅要专注于业务逻辑的Coding,并且还要在后面写上日志的处理办法,事务的开启关闭等一系列与业务逻辑无关的代码。

    log.write(class,operate)……

    效率上肯定是要打折扣的。并且,把这样的反复性的工作交给人力。是很的easy出现故障的。

     

        如今。要想提高效率。反复的工作交给机器。程序猿专心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  通过学习的深入,才发现,面向切面的编程是一种思想。无论用什么技术实现。

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

  • 相关阅读:
    20191005
    20191004-gugugu公告
    20191003
    10.2 一天
    考试总结 模拟$105$
    考试总结 模拟$104$
    考试总结 模拟$103$
    考试总结 模拟$102$
    考试总结 模拟$101$
    考试总结 模拟$100$
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6917805.html
Copyright © 2011-2022 走看看