1. 程式人生 > 實用技巧 >jdk 動態代理與 cglib 動態代理原理

jdk 動態代理與 cglib 動態代理原理

1. JDK動態代理

jdk 動態代理是通過實現被代理的介面來實現的,通過 jdk 動態代理生成的類會繼承 java.lang.reflect.Proxy,同時實現被代理的介面

舉例:為 IHello 介面生成一個動態代理類,並將它的位元組碼檔案輸出到檔案中

public interface IHello {
    public String sayHello();
}

// 通過 java.lang.reflect.Proxy 來為 IHello 生成一個代理類
IHello realObj = new HelloImpl();
IHello proxyObj = (IHello) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),realObj.getClass().getInterfaces(), invocationHandler);

斷點打在 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() { 25 try { 26 return (String)super.h.invoke(this, $Proxy0.m3, null); 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<?>[])new Class[0]); 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

跟原始碼:

1. java.lang.reflect.Proxy#newProxyInstance()
    1.1 sun.misc.ProxyGenerator#generateClassFile()
        1.1.1 sun.misc.ProxyGenerator#generateProxyClass()
            1.1.1.1 sun.misc.ProxyGenerator#generateClassFile() // line 209,直接生成 java 位元組碼陣列。裡面會繼承 java.lang.reflect.Proxy