前言
本文将带着几个问题来看
到底“动态代理”动态在哪里?InvocationHandler为什么没有任何实现?对于传入的newProxyInstance()的接口类型,是否有限制?如何确认某个类是不是代理类?动态代理的实现编写你要代理的interfacepublicinterfaceAnimal{voidsay();voidjump();}某实现了Animal的类publicclassDogextendsAnimal{publicvoidsay(){System.out.println("Iamadog.");}publicvoidjump(){System.out.println("ijumpwith4legs");}}使用InvocationHandler接口
在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口。
/***调用处理程序*/publicinterfaceInvocationHandler{Objectinvoke(Objectproxy,Methodmethod,Object[]args);}
这是固定模板的部分
中介类publicclassDynamicProxyimplementsInvocationHandler{//obj为委托类对象;privateObjectobj;publicDynamicProxy(Objectobj){this.obj=obj;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println("before");Objectresult=method.invoke(obj,args);System.out.println("after");returnresult;}}
中介类持有一个委托类对象引用,在invoke方法中调用了委托类对象的相应方法,看到这里是不是觉得似曾相识?
通过聚合方式持有委托类对象引用,把外部对invoke的调用最终都转为对委托类对象的调用。
动态生成代理类publicclassMain{publicstaticvoidmain(String[]args){//创建中介类实例DynamicProxyinter=newDynamicProxy(newDog());//获取代理类实例sellAnimalanimal=(Animal)(Proxy.newProxyInstance(Animal.class.getClassLoader(),newClass[]{Animal.class},inter));//通过代理类对象调用代理类方法,实际上会转到invoke方法调用animal.say();animal.jump();}}
文字描述太累赘,改用这样的图来表示。这就是动态代理了。
回到问题解答到底“动态代理”动态在哪里?
动态代理之所以被称为动态,是因为运行时才将它的类创建出来。代码开始执行时,还没有proxy类,它是根据需要从你传入的接口集创建的。
InvocationHandler为什么没有任何实现?
InvocationHandler不是proxy,它只是一个帮助类,proxy会把调用转发给他处理。
对于传入的newProxyInstance()的接口类型,是否有限制?
有限制。我们要传值给newProxyInstance()的一个接口数组,此数组内只能有接口,不能有类。要考虑访问限制,如果接口不是public,就需要在一个package,不同的接口内,不可有名称和参数完全一样的方法。
如何确认某个类是不是代理类?
通过isProxyClass可以进行判断,true则是动态代理类。
小结
动态代理模式,在不少流行的第三方框架中都有出现。
需要好好的学习一下。