国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JDK動態代理的理解與分析

stormjun / 3000人閱讀

摘要:類所實現的方法包裝了對被代理對象的反射調用,后文中的動態代理類正是調用此方法來調用被代理對象的方法。

前言

java的設計模式中有一項設計模式叫做代理模式,所謂代理模式,就是通過代理方來操作目標對象,而不是自己直接調用。代理又分為靜態代理和動態代理,靜態代理就是針對每個被代理對象寫一個代理類,操作不夠優雅;動態代理,可以根據接口動態的生成代理類,這動態生成的類不需要自己書寫,jdk幫你完成了。無論是動態代理還是靜態代理,最終都會產生一個代理類(class文件),里面都含有對被代理對象的封裝,只是誕生的途徑不一樣。下面我在代碼層面詳細介紹一下這兩種代理的實現和原理。

本文來自于我的博客網站http://51think.net,歡迎來訪。

一、靜態代理

1、創建手機接口 ,擁有打電話的行為

public interface MobilePhone {
    //打電話給jack
    void callJack();
}

2、創建實現類安卓手機,實現此接口

public class AndroidMobilePhone implements MobilePhone{
     private String name;
     private String age;

    public AndroidMobilePhone(String name, String age) {
        this.name = name;
        this.age = age;
    }
    //打電話給jack
    @Override
    public void callJack(){
         System.out.println(" hey boy! name="+name+",age="+age);
    }
}

3、創建靜態代理類,實現此接口

public class AndroidMobileStaticProxyPhone implements MobilePhone{
     private MobilePhone amp;

    public AndroidMobileStaticProxyPhone(MobilePhone amp) {
        this.amp = amp;
    }
    //打電話給jack
    @Override
    public void callJack(){
        System.out.println("--靜態代理前置--");
        amp.callJack();
        System.out.println("--靜態代理后置--");
    }
}

從靜態代理類AndroidMobileStaticProxyPhone 中,我們可以發現,他持有了MobilePhone 類型的對象,一旦將被代理對象傳入,它就可以操作被代理對象了。

4、創建main方法調用

如果我們不使用代理,調用是這樣的:

MobilePhone mp=new AndroidMobilePhone("杰克","23");
mp..callJack();

如果使用靜態代理,調用變成如下方式:

 MobilePhone mp=new AndroidMobilePhone("杰克","23");
 MobilePhone staticProxy=new AndroidMobileStaticProxyPhone(mp);
 staticProxy.callJack();

從上述代碼中,我們可以看出,靜態代理其實就是通過一個包裝類來調用目標對象而已。

二、動態代理

1、仍然沿用MobilePhone接口類
2、創建java.lang.reflect.InvocationHandler接口的實現類MobilePhoneHandler

public class MobilePhoneHandler implements InvocationHandler {
    private T target;

    public MobilePhoneHandler(T target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //前置處理
        System.out.println("--動態代理前置處理--");
        Object obj=method.invoke(target,args);
        //后置處理
        System.out.println("--動態代理后置處理--");
        return obj;
    }
}

關于InvocationHandler ,源碼注釋如下:

* 

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 {@code invoke} * method of its invocation handler.

即,每個代理實例都需要關聯一個invocation handler,當一個方法被代理實例調用時,這個方法會被編碼并發送到invocation handler中進行處理。這里所說的invocation handler即本文中剛剛創建的 MobilePhoneHandler 類。MobilePhoneHandler類所實現的invoke方法包裝了對被代理對象的反射調用,后文中的動態代理類正是調用此invoke方法來調用被代理對象的方法。

3、創建main方法調用

MobilePhone mp=new AndroidMobilePhone("杰克","23");
InvocationHandler handler=new MobilePhoneHandler(mp);
MobilePhone mpProxy=(MobilePhone)Proxy.newProxyInstance(MobilePhone.class.getClassLoader(),new Class[]{MobilePhone.class},handler );
mpProxy.callJack();

輸出如下:

--動態代理前置處理--
 hey boy! name=杰克,age=23
--動態代理后置處理--

在輸出內容的前置處理和后置處理中,我們可以加一些橫向的處理邏輯,這樣就變成了spring 的AOP。

關注Proxy.newProxyInstance這個方法調用,同樣是來自于java.lang.reflect包里的類。看一下源碼注釋:

     * Returns an instance of a proxy class for the specified interfaces
     * that dispatches method invocations to the specified invocation
     * handler.  This method is equivalent to:
     * 
     *     Proxy.getProxyClass(loader, interfaces).
     *         getConstructor(new Class[] { InvocationHandler.class }).
     *         newInstance(new Object[] { handler });
     * 
*

注釋中表明,這個newProxyInstance方法返回了一個特定接口代理類的實例,這個代理實例將方法調用分配給特定的invocation handler。這個Proxy.newProxyInstance方法等同于如下調用:

 Proxy.getProxyClass(loader, interfaces). getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });

我們用debug方式跟蹤一下代碼,newProxyInstance方法最終會執行到Proxy的內部類ProxyClassFactory的apply方法:

long num = nextUniqueNumber.getAndIncrement();這一行使用cas生成一個自增長的序號 。
關注ProxyGenerator.generateProxyClass 方法:

此方法動態生成一個class文件,這個class文件就是我們所說的動態代理類! 我們用代碼的方式將這個class文件寫出來:

 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", AndroidMobilePhone.class.getInterfaces());
        String path = "E:projectspaceTestincomproxyMobileProxy.class";
        try(FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(classFile);
            fos.flush();
            System.out.println("代理類class文件寫入成功");
        } catch (Exception e) {
            System.out.println("寫文件錯誤");
        }

到目錄中找到此class文件:

反編先看一下反編譯的類名和實現關系:

從此圖中可以看出,動態代理類最終還是實現了我們的MobilePhone接口,即動態代理類也是MobilePhone接口的一個實現類,它也實現了callJack方法。如下:

紅框標注this.h.invoke(this, m3, null);中的h正是我們上文中創建的MobilePhoneHandler類的對象。這樣即可完成對被代理對象的調用。類的調用關系如下:

總結

我們再看一下之前main方法中的這一行:

MobilePhone mpProxy=(MobilePhone)Proxy.newProxyInstance(MobilePhone.class.getClassLoader(),new Class[]{MobilePhone.class},handler );

現在可以得知Proxy.newProxyInstance返回的是動態生成的代理類$Proxy0的對象,也可以稱作是MobilePhone 接口的一個實現類的對象。當調用mpProxy.callJack()時,其實是調用$Proxy0.callJack(),然后對照剛剛的類調用關系圖,即可調用到被代理對象AndroidMobilePhone實例的callJack方法,從而實現了動態代理。

當我們具象的查看某一個動態代理class反編譯文件時,比如$Proxy0,它內部就是采用靜態代理的方式進行包裝。其動態是體現在,能夠在給定的接口和invocationHandler情況下,動態生成代理類,如$Proxy0,$Proxy1,$Proxy2等等,不必手動創建,使用起來更靈活。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74176.html

相關文章

  • 從源碼入手,一文帶你讀懂Spring AOP面向切面編程

    摘要:,,面向切面編程。,切點,切面匹配連接點的點,一般與切點表達式相關,就是切面如何切點。例子中,注解就是切點表達式,匹配對應的連接點,通知,指在切面的某個特定的連接點上執行的動作。,織入,將作用在的過程。因為源碼都是英文寫的。 之前《零基礎帶你看Spring源碼——IOC控制反轉》詳細講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動態代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評論0 收藏0
  • Java 代理模式 AOP

    摘要:本文首發于作者最近在學,研究了下和代理模式,寫點心得和大家分享下。所以下面來重點分析下代理模式。這里代理模式分為靜態代理和動態代理兩種,我們分別來看下。代理模式,代理,意味著有一方代替另一方完成一件事。 本文首發于 https://jaychen.cc作者 jaychen 最近在學 Spring,研究了下 AOP 和代理模式,寫點心得和大家分享下。 AOP 先說下AOP,AOP 全稱 ...

    jk_v1 評論0 收藏0
  • Java動態代理 jdk和cglib實現比較

    摘要:與靜態代理對比,動態代理是在動態生成代理類,由代理類完成對具體方法的封裝,實現的功能。本文將分析中兩種動態代理的實現方式,和,比較它們的異同。那如何動態編譯呢你可以使用,這是一個封裝了的庫,幫助你方便地實現動態編譯源代碼。 發現Java面試很喜歡問Spring AOP怎么實現的之類的問題,所以寫一篇文章來整理一下。關于AOP和代理模式的概念這里并不做贅述,而是直奔主題,即AOP的實現方...

    h9911 評論0 收藏0
  • 學Aop?看這篇文章就夠了!!!

    摘要:又是什么其實就是一種實現動態代理的技術,利用了開源包,先將代理對象類的文件加載進來,之后通過修改其字節碼并且生成子類。 在實際研發中,Spring是我們經常會使用的框架,畢竟它們太火了,也因此Spring相關的知識點也是面試必問點,今天我們就大話Aop。特地在周末推文,因為該篇文章閱讀起來還是比較輕松詼諧的,當然了,更主要的是周末的我也在充電學習,希望有追求的朋友們也盡量不要放過周末時...

    boredream 評論0 收藏0
  • Java 動態代理 理解

    摘要:之后通過類的靜態方法取得一個代理類實例再次鄙視自己。值得一提,動態代理把也代理了。總結動態代理優點相比靜態代理,不用每代理一個類就得寫一個新的代理類。缺點只能代理實現了接口的類,因為是單繼承,代理類已經是類的子類了。 動態代理 這里暫時只做JDK動態代理分析。動態代理應用廣泛,例如AOP。 showImg(https://segmentfault.com/img/bVUmAr?w=21...

    3fuyu 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<