JDK動態(tài)代理淺析

Spring框架中有一個核心的概念,叫做AOP(面向切面編程)。而AOP的本質(zhì)其實就是jdk動態(tài)代理。所以學(xué)習(xí)動態(tài)代理還是很有必要的。筆者對動態(tài)代理也只是研究了一點皮毛,如有寫的不對的地方歡迎指點。

JDK動態(tài)代理有2個很重要的東西,一個是InvocationHandler接口,還有一個是Proxy類。

先來看一下InvaocationHandler接口的定義:

InvocationHandler is the interface implemented by the invocation handler of a proxy instance. 
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

1.我們寫的每一個動態(tài)代理類都需要實現(xiàn)InvocationHandler接口。
2.每個代理類的實例都關(guān)聯(lián)著一個Handler.當(dāng)調(diào)用代理對象的方法時,其實調(diào)用的是InvocaionHandler的invoke()方法。

先來寫一個類來實現(xiàn)InvocationHandler接口:


public class MyDataInvocationHandler implements InvocationHandler {
     private Service service;
     //通過構(gòu)造函數(shù)把Service傳進來
     public  MyDataInvocationHandler(Service service) {
      this.service= service;
     }
     /**
      * proxy參數(shù):真實對象
      * method參數(shù):真實對象的方法
      * args參數(shù):給真實對象的方法傳入一些參數(shù)
      */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();//在調(diào)用真實對象的方法前加一些操作,比如事務(wù)開啟等。
        method.invoke(service, args);
        after();//在調(diào)用真實對象的方法后加一些操作,比如事務(wù)關(guān)閉等。
        return null;
    }
    
    public void before(){
        System.out.println("通知類------before()");
    }
    
    public void after(){
        System.out.println("通知類------after()");
    }
         
}

InvocationHandler先寫到這,接下來看一下Proxy類

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods. 

Proxy類提供靜態(tài)方法用來動態(tài)創(chuàng)建一個代理對象的類。

這里寫圖片描述

Proxy.newProxyInstance()方法算是最常用的一個靜態(tài)方法了。

public class Test {
    public static void main(String[] args) {
        //獲得代理類對象的實例
        /**
         * 第一個參數(shù):ClassLoader類型。一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載
         * 第二個參數(shù):一個Interface對象的數(shù)組,表示的是我將要給我需要代理的對象提供一組什么接口,如果我提供了一組接口給它,那么這個代理對象就宣稱實現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了
         * 第三個參數(shù): 一個InvocationHandler對象,表示的是當(dāng)我這個動態(tài)代理對象在調(diào)用方法的時候,會關(guān)聯(lián)到哪一個InvocationHandler對象上
         */
        Service proxyInstance = (Service) Proxy.newProxyInstance(Test.class.getClassLoader(),
                new Class<?>[] { Service.class }, new MyDataInvocationHandler(new ServiceImpl()));
        proxyInstance.update();
         
    }
    }

下面是我的Service接口和Service的實現(xiàn)類。

public interface Service {
     void update();     
}
public class ServiceImpl implements Service {

    @Override
    public void update() {
          System.out.println("這是被代理Service的實現(xiàn)類----update");
    }

}

運行一下:

這里寫圖片描述

好了。效果出來了。但估計會有許多疑問吧。為什么他會自動的調(diào)用InvocationHandler的invoke()方法???待會再解釋。。。

在上面Test測試類中通過Proxy.newProxyInstance生成的實例是屬于哪一個類的呢?通過項目工程,沒有找到該特殊的類。debug看一下。

這里寫圖片描述

我們看到,proxyInstance實例的類名叫做:"$Proxy0",默認(rèn)動態(tài)代理類的類名取名方式是:"$"+Proxy關(guān)鍵字+一個數(shù)字的形式,我們也可以修改這個名字。

其實這個類是運行在內(nèi)存中的。我們可以用流的形式將該類的二進制寫到硬盤中的.class文件中,再通過反編譯工具看一下源代碼到底是什么!

在測試類中加這樣一個方法

private static void createProxyClass() {
              byte[] bs = ProxyGenerator.generateProxyClass("MyProxy",new Class<?>[] { Service.class }) ;
              try {
                FileOutputStream fileOutputStream = new FileOutputStream("d://a.class");
                fileOutputStream.write(bs);
                fileOutputStream.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

筆者剛開始用到ProxyGenerator的時候,始終報錯,包倒不過來,這個百度自己查一下,有解決方案的。。。

ProxyGenerator.generateProxyClass()方法的第一個參數(shù)就是修改了類名。

通過反編譯工具終于看到了這個神秘的java代碼


這里寫圖片描述

這里寫圖片描述

這里寫圖片描述

關(guān)鍵代碼已經(jīng)畫了框框了。對于上面提的那個問題,在2中已經(jīng)給了答案了。

聲明:筆者還只是一個小小的菜鳥,目前還在讀大三中,對于有些問題或許理解的還不夠透徹,歡迎指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容