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 }
View Code

相关文章: