zoukankan      html  css  js  c++  java
  • 动态代理的事务封装

             在上篇博客中介绍了使用ThreadLocal维护Connection的方法,这样做的最大的优点就是不用来回的传递Connection了,可是我们有会发如今我们使用事务的时候不可避免的会写很多反复的代码,这些都是与业务逻辑无关的:          

            Connection conn = ConnectionManage.GetConnection();
            ConnectionManage.beginTransaction(conn); 
            ConnectionManage.commitTransaction(conn);//等等代码。

    //以及Catch中的事务回滚,和finally中关闭连接等等


    
    

    
    

            不仅不合理。并且是反复劳动,程序开发的一个原则就是杜绝反复劳动。做到良好的封装。

            这里,我们就採用动态代理对事务进行封装,使我们的业务逻辑层不再出现有关事务的代码。

    package com.hanyi.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 hanyi
     *
     */
    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); 


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    js对象的所有方法
    js数组的所有方法
    Scss语法
    new一个对象的过程
    promises的深入学习
    jsonp的原理介绍及Promise封装
    Vue页面缓存和不缓存的方法
    JavaScript数据类型
    JS常用函数原理的实现
    @Autowired注解在抽象类中实效的原因分析
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4624365.html
Copyright © 2011-2022 走看看