關於jdk的proxy看了幾遍,每次記住了,過了一段時間,又容易忘記 java
今天仔細看了一下,發現實際上Proxy.newInstance就是動態生成了一個Proxy.class文件,而後我用jad反編譯以後發現,就是生成了一個類,implement以前寫的interface,而後全部的方法都寫成final了 數組
反編譯後代碼以下 this
public final int say(String s, String s1) { try { return ((Integer)super.h.invoke(this, m3, new Object[] { s, s1 })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final ArrayList list(String s, int i) { try { return (ArrayList)super.h.invoke(this, m4, new Object[] { s, Integer.valueOf(i) }); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } }
如今代理類生成了,如何調用hander裏面的invoke呢 代理
步驟1.Class cl = getProxyClass(loader, interfaces); 獲取代理類的class code
步驟2.Constructor cons = cl.getConstructor(constructorParams); 獲取proxy的子類的構造方法 對象
constructorParams 的值爲 new class[]{invocationhandler.class}; 繼承
步驟3.獲取實體類對象 接口
return (Object) cons.newInstance(new Object[] { h }); get
由於生成的代理類繼承Proxy,實現了咱們傳進去的接口,全部接口執行方法,直接調用生成的Proxy裏面的final方法,返回結果就是,調用傳進去的handler的invoke方法,參數this, it
return (ArrayList)super.h.invoke(this, m4, new Object[] { s, Integer.valueOf(i) }); 第一個參數就是當前Proxy,第二個是方法Method,第三個是args
還有Object... args這種參數實際上編譯之後是object[] 數組,是java的語法糖
而後就執行咱們的handler裏面定義的invoke方法了
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("aaa:"+proxy.getClass().getName()); Object temp =method.invoke(this.o, args); return temp; }
如下附java生成字節碼方法:
public class ProxyGeneratorUtils { /** * 把代理類的字節碼寫到硬盤上 * @param path 保存路徑 */ public static void writeProxyClassToHardDisk(String path) { // 第一種方法,這種方式在剛纔分析ProxyGenerator時已經知道了 // System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true); // 第二種方法 // 獲取代理類的字節碼 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", SujectImpl.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(path); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { ProxyGeneratorUtils.writeProxyClassToHardDisk("F:/$Proxy11.class"); } }你們能夠試一下