代理模式分为静态代理和动态代理两种
1.静态代理:就是在编写代码的过程中由开发人员硬编码
public class Person{ public void sleep(){ System.out.println("我要睡觉了"); } }
public class Proxy{ private Person p = new Person(); public void preSleep() { doSomething(); p.sleep(); }
}
代理对象始终维护了一个被代理对象的应用,当用户需要使用被代理对象时,使用代理对象而不直接使用被代理对象。这样就能实现在调用具体方法前后做出一些操作。
2.动态代理:代理类在程序运行时创建代理的方式成为动态代理
动态代理的创建需要使用到java.lang.reflect包下的Proxy类和InvocationHandler接口。
Proxy类有一个快速创建代理类对象的方法
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数:
loader:需要传入一个类加载器,由这个ClassLoader对象来对生成的代理对象进行加载。
interfaces:接口数组,传入一个接口数组,代理对象会实现其中的接口,从而使代理对象能够调用其中的方法。
InvocationHandler :InvocationHandler对象,其中就是实现代理类所代理(增强)功能。传入此对象将会把代理对象和此handler关联到一起。
下面是具体的代码:
class ZCL implements dayLife{ @Override public void BuyIce() { System.out.println("买个棒棒冰!"); } @Override public String getMoney(String name) { System.out.println(name+"!钱交上来!"); return "上交100块"; } }
ZCL zcl = new ZCL();//被代理的真实对象 dayLife proxy = (dayLife)Proxy.newProxyInstance(zcl.getClass().getClassLoader(), zcl.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前:"+proxy.getClass()); Object invoke = method.invoke(zcl, args); return args==null?invoke:args[0].toString()+invoke; } });//代理对象 proxy.BuyIce(); String money = proxy.getMoney("李华");
执行结果: 方法执行前:class com.sun.proxy.$Proxy0 买个棒棒冰! 方法执行前:class com.sun.proxy.$Proxy0 李华!钱交上来! 李华上交100块
InvocationHandler对象可以使用创建类的方式,我这里使用的是匿名类演示方便一点。
所以实质上动态代理的运行原理是将方法的执行委托给InvocationHandlerd对象的的invoke方法执行,InvocationHandler对象持有一个被代理对象的实例。
这样就可以在invoke方法中实现对代理方法的增强,而且不需要向静态代理那样每个方法都进行编码,因为生成的代理类中的方法执行都是通过InvocationHandler的invoke方法执行的,
所以只需要在invoke方法中进行方法的增强就可以了。
执行后打印的class名称为$Proxy0,是因为这是由jdk自动生成的名称,后面依次按0,1,2....
我们再来看一下jdk动态生成的字节码文件,因为是直接生成在内存当中的,我们可以使用一下方法保存到磁盘上。
byte[] generateProxyClass = ProxyGenerator.generateProxyClass(proxy.getClass().getSimpleName(),proxy.getClass().getInterfaces()); try(FileOutputStream fileOutputStream = new FileOutputStream(new File("C:/Users/xxx/Desktop/$Proxy0.class"))){ fileOutputStream.write(generateProxyClass); fileOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); }
然后再使用反编译软件进行查看,我这里使用的是JD。下面是代码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import test.dayLife; public final class $Proxy0 extends Proxy implements dayLife{ private static Method m1; private static Method m3; private static Method m2; private static Method m4; private static Method m0; public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject)throws { try{ return ((Boolean)this.h.invoke(this, m1, new Object[] {paramObject })).booleanValue(); } catch (Error|RuntimeException localError){ throw localError; }catch (Throwable localThrowable){ throw new UndeclaredThrowableException(localThrowable); } } public final void BuyIce() throws { try{ this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; }catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() throws { try{ return (String)this.h.invoke(this, m2, null); }catch (Error|RuntimeException localError){ throw localError; }catch (Throwable localThrowable){ throw new UndeclaredThrowableException(localThrowable); } } public final String getMoney(String paramString) throws { try{ return (String)this.h.invoke(this, m4, new Object[] { paramString }); }catch (Error|RuntimeException localError){ throw localError; }catch (Throwable localThrowable){ throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode()throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException localError){ throw localError; } catch (Throwable localThrowable){ throw new UndeclaredThrowableException(localThrowable); } } static{ try{ m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("test.dayLife").getMethod("BuyIce", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m4 = Class.forName("test.dayLife").getMethod("getMoney", new Class[] { Class.forName("java.lang.String") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; }catch (NoSuchMethodException localNoSuchMethodException){ throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); }catch (ClassNotFoundException localClassNotFoundException){ throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }
最下面是静态代码块,首先会使用反射加接口的方法引用到成员变量,而构造函数是调用父类的构造函数,将InvocationHandler赋值给成员h,执行方法时使用InvocationHandler
的invoke方法去执行真正被代理对象的方法,这就是动态代理类的真面目。
原文:https://www.cnblogs.com/nubea/p/12186825.html