zoukankan      html  css  js  c++  java
  • 代理方法动态代理模式封装事务详解

    本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~

        代理,大家都知道是什么意思。百科上面的解释:以他人的名义,在授权范围内停止对被代理人直接产生法律效力的法律行为。

        说白了就是A想交女朋友,但是自己不敢去表白,然后叫B去帮他送花,而B帮助A送了花,B就是代理。

        而代理又分为静态代理和动态代理,那么什么是静态代理呢?

        仍然是上面的例子,A想交女朋友,然后就就跟B说:B啊,咱俩是哥们儿,我喜欢那么女生,你要帮我送一束花,帮我送洋娃娃,帮我送巧克力……然后A想送的时候,就叫B去送响应的货色。

        动态代理是:A告诉B,你去帮我送花,然后B就去送花;A又说你去帮我送洋娃娃,B就又去送洋娃娃……

        

        那么静态代理和动态代理有什么区别呢?静态代理提早都知道要帮A做那些事儿,有心理预备,行动起来比较快。但是由于A非常啰嗦,A需要表达激烈的爱意,跟B说了一大顿,B都需要记下A要干啥,到时候去帮A做。

        而动态代理是,B始终忙自己的事儿,当A有需求的时候,就帮A去送货色,由于A没有提早告诉B要送什么,所以B要去现预备,所以需要花费一些时间去预备。

        

        好了,说了这么多空话,就是为了用我自己的懂得讲解一下代理模式。上面停止正题——动态代理。

        所谓动态代理,就是在运行时动态地创立一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。

        代理和方法

        

        Proxy代理完全是java创立的,并且实现完全的subject接口。

        InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject详细行为类的访问。

        sun已经帮我们创立好了代理类Proxy,我们需要做的就是告诉Proxy:我们要做什么。我们不能像以前一样将代码写入到Proxy中,因为它不是我们创立的。如果我们自己创立Proxy,那就是静态代理了,这里会有大量的重复代码,是我们不想看到的。由于InvocationHandler能够响应代理的任何调用,我们可以把InvocationHandler想成是代理收到方法调用后,请求做际工作的对象。

        

        上面通过动态代理封装事务的例子停止讲解:

        事务在之前的项目中始终是加在Manager层,Manager层调用不同的dao方法,同时担任开启事务,执行事务等。而由于每个Manger层的每个方法里头除了要关心业务逻辑以外,都需要担任事务的开关。其实事务是独自的逻辑,我们可以动态代理分离开来。

        每日一道理
    谁说人与人隔着遥远的重洋,谁说心与心设着坚固的堤防?十六岁的鸟儿飞上天空,总会找到落脚的枝头。
    package com.xxjstgb.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 liuzhengquan
     * 
     */
    public class TransactionHandler implements InvocationHandler {
    
    	//要处理的对象,声明为Object类型是为了通用性
    	private Object targetObject;
    	
    	//动态生成方法被处理过后的对象 
    	public Object newProxyInstance(Object targetObject) {
    		this.targetObject = targetObject;
    		/**
    		 * 参数1:类的加载器
    		 * 参数2:肯定继承类的接口
    		 */
    		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 {
    			//获得Connection
    			conn = ConnectionManager.getConnection();
    			//System.out.println(method.getName());
    			/*
    			 * 判断Manager层调用的什么方法,调用该方法时,主动开始事务
    			 *注:此处DRP视频中有错误
    			 */
    			if(method.getName().startsWith("addFlowCard") || 
    			   method.getName().startsWith("delFlowCard") || 
    			   method.getName().startsWith("modifyFlowCard") || 
    			   method.getName().startsWith("findFlowCardList") || 
    			   method.getName().startsWith("findClient") || 
    			   method.getName().startsWith("findAimClient") 
    			   ){
    				System.out.println(method.getName());
    				// 手动开启事务
    				ConnectionManager.beginTransaction(conn);
    			}
    			//调用目标对象的业务逻辑方法
    			ret=method.invoke(targetObject, args);
    			if(!conn.getAutoCommit()){
    				//提交事务
    				ConnectionManager.commitTransaction(conn);
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    			//使用代理后,代理用InvocationTargetException包装了异常
    			if(e instanceof InvocationTargetException){
    				InvocationTargetException ete=(InvocationTargetException)e;
    				throw ete.getTargetException();
    			}
    			if(!conn.getAutoCommit()){
    				//回滚事务
    				ConnectionManager.rollbackTransaction(conn);
    			}
    			throw new ApplicationException("操作失败!");
    		}
    		finally{
    			//关闭事务,并删除连接
    			ConnectionManager.closeConnection();
    		}
    		return ret;
    	}
    
    }

        这里的Invoke方法,当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。在Invoke方法里头,能够失掉RealSubject详细行为方法,并且能够定义新的行为,也就是这里的事务操作。

        

        *注:视频中这里有错误,method.getName()获得是调用的Manager方法,而不Servlet的方法。

        

        对应Servlet的调用:

    public class FlowCardServlet extends HttpServlet {
    	//私有声明详细行为类对象
    	private FlowCardManager flowCardManager;
    	@Override
    	public void init() throws ServletException {
    		flowCardManager=(FlowCardManager)getBeanFactory().getServiceObject(FlowCardManager.class);
    		//采取动态代理包装service
    		TransactionHandler transactionHandler=new TransactionHandler();
    		//对目标生成代理对象
    		flowCardManager=(FlowCardManager)transactionHandler.newProxyInstance(flowCardManager);
    	}
         }

        这样我们就创立了flowCardManager代理,当我们想调用Manager层的方法等,我们就可以通过在Servlet方法中通过使用flowCardManager代理对象,停止事务操作以及Manager层方法调用。

        动态代理的应用非常广范,比如WebService的应用,其实就是动态代理的一个应用。我们对WebService添加的引用,其实就是一个远程代理,然后客户端通过代理能够停止远程访问。

        生活中和现实应用中还有很多,都有代理的原型。希望大家多多与我交流,共同进步。

    文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

    --------------------------------- 原创文章 By
    代理和方法
    ---------------------------------

  • 相关阅读:
    VS2008编写MFC程序--使用opencv2.4()
    November 02nd, 2017 Week 44th Thursday
    November 01st, 2017 Week 44th Wednesday
    October 31st, 2017 Week 44th Tuesday
    October 30th, 2017 Week 44th Monday
    October 29th, 2017 Week 44th Sunday
    October 28th, 2017 Week 43rd Saturday
    October 27th, 2017 Week 43rd Friday
    October 26th, 2017 Week 43rd Thursday
    October 25th, 2017 Week 43rd Wednesday
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3111408.html
Copyright © 2011-2022 走看看