package reflect;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import static java.lang.System.out;interface User{public abstract void say(String str);}class UUU implements User{@Overridepublic void say(String str) {out.print(str);}}public class ProxyTest {public Object target = null;public static void main(String args[])throws Exception {//System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); // 通過此語句得到動態產生 的class 檔案,然後通過 反編譯工具得到代碼 User prox = (User)(new ProxyTest().bind(new UUU()));// 動態得到 proxy類,這個類繼承proxy,且實現User 介面}public static void proxyConstruct()throws Exception{Class<?> clazz = Proxy.getProxyClass(Comparable.class.getClassLoader(),Comparable.class);Constructor cons = clazz.getConstructor(InvocationHandler.class);Object proxy = cons.newInstance(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {return null;}});out.println(proxy.toString());}public static void proxyInstance()throws Exception {Object proxy = Proxy.newProxyInstance(Comparable.class.getClassLoader(),new Class<?>[] {Comparable.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}});out.println(proxy==null);}public Object bind(final Object target){this.target = target ;return Proxy.newProxyInstance(Comparable.class.getClassLoader(),new Class<?>[] {Comparable.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {out.println("begin:");return method.invoke(target, args); // 對於代理所執行的任何方法都將轉移到這個地址執行,這也是就為什麼可以添加功能的原因 }});}}/* * Proxy 原理 * Proxy 就是動態產生一個,其實 這和代理並沒有什麼關係,它只是可以動態地去產生一個類,在產生 * 這個類的時候,我們可以規定它的載入器,實現的介面,而Proxy 產生的這個類並代理目標類做什麼,所以裡面還有一個重要的成員 InvocationHandler h * * 下面我們來分析一下 目標類(target)、代理類(proxy)、InvocationHandler(Handler)類 它們之間的關係 * * 當我們調用代理類中實現介面的方法時,如proxy.add(),會將方法名傳給 代理類的 InvocationHandler 成員,而這個成員有一個 invoke 方法,所以我們 * 調用 proxy.add 則成了 h.invoke(this,method,args);而調用h.invoke方法,又不得不調用我們實現的invocationHandler介面裡面的 invoke 方法, * 而我們則在 handler.invoke 方法中調用 根據傳過來的方法Method調用 Method.invoke(target,args),即,這樣就成功調用了目標類裡的方法 * * 因為代理類調用的所有的方法都變了 h.invoke(proxy,method,args)調用方法,而在invoke 中又知道了方法的method ,即讓方法調用對象 method.invoke(target,args) * 因為代理類始終是自己,所以就變成了h.inovoke(this,method,args) * * */
下面是反編譯得到的動態類,實現Comparable 介面
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class Proxy0 extends Proxy implements Comparable{ private static Method m3; private static Method m1; private static Method m0; private static Method m2; public Proxy0() throws { super(paramInvocationHandler); } public final int compareTo() throws { try { return ((Integer)this.h.invoke(this, m3, new Object[] { paramObject })).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final boolean equals() throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() throws { try { return ((String)this.h.invoke(this, m2, null)); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m3 = Class.forName("java.lang.Comparable").getMethod("compareTo", new Class[] { Class.forName("java.lang.Object") }); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } }}