標籤:
0x01 描述
”動態代理中的動態,是針對使用java代碼實際編寫了代理類的“靜態”代理而言的,它的優勢不在於省去了編寫代理類的那一點工作量,而是實現了可以在原始類和介面還未知的時候,就可以確定代理類的行為,當代理類與原始類脫離直接聯絡後,就可以很靈活地重用於不同的應用情境中" 引自 《深入理解java虛擬機器 java進階特性與最佳實務》。
它的缺點:因為java中類只支援單繼承,而代理類有個共同的父類Proxy,所有註定了動態代理不能為類成員方法作代理的缺陷。
0x02 demo
package test;public interface IWorker { Object work(Object... objects);}
package test;public class Worker implements IWorker { @Override public Object work(Object... objects) { System.out.println("Working ..."); return "work method"; }}
package test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class Handler implements InvocationHandler { IWorker mWorker; Handler(IWorker iWorker) { this.mWorker = iWorker; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("equals")) { System.out.println("the equals method will always return true"); return true; } else if (method.getName().equals("hashCode")) { System.out.println("yes, the hashCode is "); } else if (method.getName().equals("toString")) { System.out.println("toString method has been called"); } return method.invoke(mWorker, args); }}
package test;import java.lang.reflect.Proxy;public class Test { public static void main(String[] args) { System.getProperties().put( "sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); IWorker worker = (IWorker) Proxy.newProxyInstance( IWorker.class.getClassLoader(), Worker.class.getInterfaces(), new Handler(new Worker())); System.out.println(worker.work()); System.out.println(worker.equals(null)); System.out.println(worker.toString()); System.out.println(worker.hashCode()); }}
0x03 動態產生的代理類的代碼
package com.sun.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;import test.IWorker;public final class $Proxy0 extends Proxy implements IWorker{ private static Method m1; private static Method m2; private static Method m3; 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 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 Object work(Object[] paramArrayOfObject) throws { try { return (Object)this.h.invoke(this, m3, new Object[] { paramArrayOfObject }); } 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") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("test.IWorker").getMethod("work", new Class[] { Class.forName("[Ljava.lang.Object;") }); 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()); } }} 0x04 注意
1、動態產生的方法都是final的
2、除了介面中的方法外,預設它還覆蓋了Object類中的toString、hashCode和equals方法
3、每個方法都進行了異常的捕捉,雖然對異常進行了簡單的分類處理,但是仍然使用了奇怪的文法將捕捉到的運行時異常照常拋出,所以在使用到代理類的地方照樣可以使用正常的異常出來邏輯來處理運行時拋出的異常
java 動態代理