關於動態代理原理

關於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);
        }
    }



原理是,proxy經過newProxyInstance傳遞參數,加載器,全部interface,還有invocatoinhandler實現類,根據getProxyClass 獲取被代理類,而後反射讀取被代理的構造方法,實現全部接口

如今代理類生成了,如何調用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;
	}



返回的結果就是方法執行的結果,void也是一種object


如下附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");  
	}
}
你們能夠試一下
相關文章
相關標籤/搜索