1. JDK 动态代理
jdk 动态代理是通过实现被代理类的接口来实现的,通过 jdk 动态代理生成的类会继承 java.lang.reflect.Proxy,同时实现被代理类的接口。
由于 jdk 动态代理已经继承了 java.lang.reflect.Proxy,所以它就不能通过继承类的方式来实现动态代理了,所以选择了实现接口的方式来生成动态代理。
举例:为 IHello 接口生成一个动态代理类,并将它的字节码文件输出到文件中
(不管是动态生成的类,还是普通的类,最后都需要拿到二进制的字节码数组,然后通过 classloader 加载到 jvm 中,所以,不管是什么类,理论上我们都可以将它的字节码数组拿到并输出到文件中)
1 public interface IHello { 2 public String sayHello(String name); 3 } 4 5 // 通过 java.lang.reflect.Proxy 来为 IHello 生成一个代理类 6 IHello realObj = new HelloImpl(); 7 IHello proxyObj = (IHello) Proxy.newProxyInstance(realObj.getClass().getClassLoader(), 8 realObj.getClass().getInterfaces(), new InvocationHandler() { 9 @Override 10 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 11 // 方法执行前可以插入逻辑 12 // 执行被代理类的方法 13 Object obj = method.invoke(realObj, args); 14 // 方法执行后可以插入逻辑 15 return obj; 16 } 17 });
断点打在 java.lang.reflect.Proxy.ProxyClassFactory#apply() Line 642 处
调用如下代码,将字节码文件进行输出,然后拿到文件反编译
new FileOutputStream("d:\\a.class").getChannel().write(ByteBuffer.wrap(proxyClassFile))
1 public final class $Proxy0 extends Proxy implements IHello 2 { 3 private static Method m1; 4 private static Method m3; 5 private static Method m2; 6 private static Method m0; 7 8 public $Proxy0(final InvocationHandler invocationHandler) { 9 super(invocationHandler); 10 } 11 12 public final boolean equals(final Object o) { 13 try { 14 return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o }); 15 } 16 catch (Error | RuntimeException error) { 17 throw; 18 } 19 catch (Throwable t) { 20 throw new UndeclaredThrowableException(t); 21 } 22 } 23 24 public final String sayHello(final String s) { 25 try { 26 return (String)super.h.invoke(this, $Proxy0.m3, new Object[] { s }); 27 } 28 catch (Error | RuntimeException error) { 29 throw; 30 } 31 catch (Throwable t) { 32 throw new UndeclaredThrowableException(t); 33 } 34 } 35 36 public final String toString() { 37 try { 38 return (String)super.h.invoke(this, $Proxy0.m2, null); 39 } 40 catch (Error | RuntimeException error) { 41 throw; 42 } 43 catch (Throwable t) { 44 throw new UndeclaredThrowableException(t); 45 } 46 } 47 48 public final int hashCode() { 49 try { 50 return (int)super.h.invoke(this, $Proxy0.m0, null); 51 } 52 catch (Error | RuntimeException error) { 53 throw; 54 } 55 catch (Throwable t) { 56 throw new UndeclaredThrowableException(t); 57 } 58 } 59 60 static { 61 try { 62 $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); 63 $Proxy0.m3 = Class.forName("com.cn.zsy.proxy.jdkProxy.IHello").getMethod("sayHello", Class.forName("java.lang.String")); 64 $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]); 65 $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]); 66 } 67 catch (NoSuchMethodException ex) { 68 throw new NoSuchMethodError(ex.getMessage()); 69 } 70 catch (ClassNotFoundException ex2) { 71 throw new NoClassDefFoundError(ex2.getMessage()); 72 } 73 } 74 }