<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    少年阿賓

    那些青春的歲月

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

    java動態代理和cglib動態代理在工作中用代理的地方非常多,但一直還沒仔細來看代理的原理,今天被同事提到,所以自己開始仔細研究了一下這兩者代理都做了些什么工作,并通過編寫測試用例的方式來對兩種代理原理作理解。
    在自行看代碼之前,初步問了一下朋友,大概解釋這兩者區別是,java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。這是朋友說的,我并沒自己實驗過,所以也沒映象,所以開始自己動手實踐之:
    java動態代理

    使用方法:

    接口:

    public interface Call {
    void doCall(String doCall);
    }

    public interface Processor {
    void doProcess(String doProcess);
    }

    實現類:

    public class ServiceImpl implements Call, Processor {

    public void doCall(String doCall) {
    System.out.println("doCall");
    }

    public void doProcess(String doProcess) {
    System.out.println("doProcess");
    }
    }

    具體代理Handler:

    public class ServiceHandler implements InvocationHandler {

    private Call callService;

    public ServiceHandler(Call callService) {
    this.callService = callService;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    System.out.println("proxyMethod=" + method.getName());
    Object obj = method.invoke(this.callService, args);
    System.out.println("after invoke!");
    return obj;
    }

    }

    使用java動態代理:

    public class JdkProxyTest {   
    @Test
    public void testJdkProxy() {
    Call call = new ServiceImpl();
    ServiceHandler handler = new ServiceHandler(call);
    Call callProxy = (Call) Proxy.newProxyInstance(call.getClass().getClassLoader(),
    new Class[]{Call.class}, handler);
    callProxy.doCall("test");
    }
    }

    最終效果就是執行代理接口的doCall方法之前,該方法被ServiceHandler給處理了。

    通過查看java.lang.reflect.Proxy代碼,大致擬了一下它的實現原理:
    1. 取到new Class[]{Call.class}這里所有接口,通過Class.forName把接口類加載到JVM,放到內部Set里保存,把接口的完善名字保存,帶包名的接口名字,并以把這組接口名稱數組轉換成List作為key,用于下面生成代理類后保存到內部Map的key.也就是相當于這一組的接口名稱對應的一個生成的代理類
    2. 主要是從內存里找是否之前已經生成好了這同一組接口的代理類,如果有就直接拿出。這里第一次是需要新建立的,所以開始創建代理,首先檢查代理目標接口的訪問控制符是否是默認包級別的,如果是就需要給生成的代理類設置目標接口同樣的包名,才能默認訪問這種級別下的接口。如果這種有默認訪問控制標識符的目標接口,又有不同包名的目標接口,則會報出錯誤。否則其它情況,是給的無包名的代理類,生成的代理類的默認名稱是$Proxy開頭加Proxy里標識唯一類名的數字,是靜態long型變量,每次生成一次代理類會累加
    3. 調用ProxyGenerator.generateProxyClass(proxyName, interfaces)動態生成class字節碼類,該類相當于是Proxy的子類,實現了需要代理的接口方法,并在每個方法里調用了InvocationHandler的invoke方法,而我們自己實現的InvocationHandler接口類里完成了以反射方式最終對目標業務類的接口方法進行調用。所以此種方式實現的動態代理只能代理接口方法,對具體類的代理不能實現。

     

    http://hi.baidu.com/dobug/blog/item/493f817e802479340cd7dab9.html

    posted on 2012-06-07 21:51 abin 閱讀(706) 評論(0)  編輯  收藏 所屬分類: java基礎知識

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久精品国产精品亚洲| 亚洲日韩乱码中文无码蜜桃臀网站| 国产精品免费观看视频| 亚洲午夜在线一区| 亚洲精品免费观看| 亚洲一区二区三区无码中文字幕| 国产自产拍精品视频免费看| 69xx免费观看视频| 日韩精品内射视频免费观看| 久久精品成人免费国产片小草| 美女扒开屁股让男人桶爽免费 | 激情无码亚洲一区二区三区| 91午夜精品亚洲一区二区三区| 亚洲AV无码乱码国产麻豆| 在线亚洲精品自拍| 亚洲中文字幕无码专区| 国产中文字幕免费观看| 高清国语自产拍免费视频国产 | 亚洲一级毛片免观看| 亚洲综合一区二区精品久久| 久久亚洲精品成人综合| 久久夜色精品国产亚洲| 亚洲AV无码久久精品狠狠爱浪潮 | 亚洲精品中文字幕| 亚洲自偷自偷在线成人网站传媒| 亚洲精品午夜视频| 亚洲国产精品线观看不卡| 亚洲成年人免费网站| 亚洲国产午夜精品理论片| 亚洲国产成人资源在线软件| 精品亚洲成a人片在线观看少妇| 久久久久久亚洲精品中文字幕| 亚洲免费观看视频| 婷婷久久久亚洲欧洲日产国码AV| 亚洲A∨无码一区二区三区 | 国产午夜精品久久久久免费视| 国产自国产自愉自愉免费24区| 暖暖免费在线中文日本| 1a级毛片免费观看| 无码高潮少妇毛多水多水免费| 日韩电影免费在线观看视频|