设计模式--动态代理(JDK)

    上篇博客中敲了一个小例子,关于静态代理的。《设计模式--代理模式》博客的最后留下了一个疑问,追求者小明如果希望为每一个方法添加一个测试方法,测试看看代理人的工作效率。这篇博客将继续……

    在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以额生成JDK动态代理类或动态代理对象。

    Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果在程序中为一个或多个接口动态的生成实现类,就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态的创建实例,也可以使用Proxy来创建动态代理实例。

    1 先写了一个专门测试时间的类

package dahuashejimoshiv3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * @author yingjie
 * 调用处理程序--专门用于调用被代理对象方法的处理
 */
public class TestTime implements InvocationHandler {
	private Object target;	           //定义被代理对象
    public  TestTime(Object target) {  
		this.target=target;
	}
    /**
     * proxy:代表动态代理对象
     * method:正在执行的方法
     * args:调用目标方法时传入的参数
     */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) //继承Proxy类的invoke方法
			throws Throwable {
		long startMovieTicket=System.currentTimeMillis();  
	    System.out.println("开始时间:"+startMovieTicket);        
		System.out.println(proxy.getClass().getName()+"颖杰进行测试,哈哈");
		
		method.invoke(target);//通过反射以target为主调来执行method方法,这就是回调了target对象的原有方法。
		
		long endMovieTicket=System.currentTimeMillis();  
        System.out.println("所用时间:"+(endMovieTicket-startMovieTicket)); 
		return null;
	}

}

   2 客户端调用:

package dahuashejimoshiv1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import dahuashejimoshi.v2.PursuitMethod;
import dahuashejimoshi.v2.PursuitProxy;
import dahuashejimoshiv3.TestTime;

public class Client {
	public static void main(String[] args){				
		SchoolGirl mmGirl=new SchoolGirl();		
		Pursuer xiaomingPursuiter=new Pursuer(mmGirl);
		PursuitMethod pursuitProxy= new PursuitProxy(xiaomingPursuiter);
		//创建一个invocationHandler 对象
		InvocationHandler testUseTime=new TestTime(pursuitProxy);
		//使用Proxy直接生成一个动态代理对象
		PursuitMethod sMethod=(PursuitMethod)Proxy.newProxyInstance(pursuitProxy.getClass().getClassLoader(), pursuitProxy.getClass().getInterfaces(), testUseTime);
		//调用生成的动态代理对象的方法
		sMethod.sendFlowers();
		sMethod.sendFootball();
		sMethod.sendMovieTicket();
	}

}


3 显示结果:

开始时间:1432891462497
com.sun.proxy.$Proxy0颖杰进行测试,哈哈
追求者小明送给mm花
代理帮忙送花
所用时间:0
开始时间:1432891472415
com.sun.proxy.$Proxy0颖杰进行测试,哈哈
追求者小明送给mm足球
代理帮忙送球
所用时间:0
开始时间:1432891472415
com.sun.proxy.$Proxy0颖杰进行测试,哈哈
追求者小明送给mm电影票
代理帮忙送电影票
所用时间:0


4 提出疑问,JDK的Proxy和InvocationHandler到底是怎样实现动态代理的呢?

无论是静态代理还是动态代理都离不开一个代理类,他们不同的是静态代理我们可以自己创建,它是看得到摸得着得。而如果我们使用JDK为我们封装的动态代理,它会根据我们的提供的条件自动为我们创建一个代理类。模拟jdk写了一下生成的动态代理类proxy1,如下图的最左边类,在被创建的动态代理同样实现共同的接口PursuitMehtod,重写接口中的方法。当客户端调用动态代理类的中的方法时,调用继承自InvocationHandle的TestTime类,然后在TestTime的invoke的方法中通过反射回调被代理对象的原有方法。

设计模式--动态代理(JDK)_第1张图片


5 使用动态代理的好处?

   (1)在不改变原有类的基础上,对类附加更多的操作。它是无侵入式的代码扩展


6 总结: 

    看了关于动态代理的资料,觉得动态代理没有那么难。JDK封装的动态代理类Proxy中关键点就是反射。Method的反射,对于这一点还没有研究,以后的文章中将介绍。  



你可能感兴趣的:(设计模式,java)