1. 程式人生 > >java動態代理——JDK和CGLIB原理解析與使用

java動態代理——JDK和CGLIB原理解析與使用

CGLIB的動態代理 

原理

      代理為控制要訪問的目標物件提供了一種途徑。當訪問物件時,它引入了一個間接的層。JDK自從1.3版本開始,就引入了動態代理,並且經常被用來動態地建立代理。JDK的動態代理用起來非常簡單,當它有一個限制,就是使用動態代理的物件必須實現一個或多個介面。如果想代理沒有實現介面的繼承的類,該怎麼辦?現在我們可以使用CGLIB包。

二、什麼是cglib

     CGLIB是一個強大的高效能的程式碼生成包。

      1>它廣泛的被許多AOP的框架使用,例如:spring AOP和dynaop,為他們提供方法的interception(攔截);

       2>hibernate使用CGLIB來代理單端single-ended(多對一和一對一)關聯(對集合的延遲抓取,是採用其他機制實現的);

       3>EasyMock和jMock是通過使用模仿(moke)物件來測試Java程式碼的包。

     它們都通過使用CGLIB來為那些沒有介面的類建立模仿(moke)物件。

三、底層

      CGLIB包的底層是通過使用一個小而快的位元組碼處理框架ASM(Java位元組碼操控框架),來轉換位元組碼並生成新的類。除了CGLIB包,指令碼語言例如 Groovy和BeanShell,也是使用ASM來生成java的位元組碼。當不鼓勵直接使用ASM,因為它要求你必須對JVM內部結構包括class檔案的格式和指令集都很熟悉。所以cglib包要依賴於asm包,需要一起匯入。下圖為cglib與一些框架和語言的關係(CGLIB Library and ASM Bytecode Framework)

      Spring AOP和Hibernate同時使用JDK的動態代理和CGLIB包。Spring AOP,如果不強制使用CGLIB包,預設情況是使用JDK的動態代理來代理介面。

四、例項場景模擬

1. 我們建立一個對Table操作的DAO類,提供了CRUD方法。 
    BookServiceBean.java

  1. package com.tech.cglibx;  
  2. publicclass BookServiceBean {  
  3.  publicvoid create(){     
  4.         System.out.println("create() is running !"
    );     
  5.     }     
  6.     publicvoid query(){     
  7.         System.out.println("query() is running !");     
  8.     }     
  9.     publicvoid update(){     
  10.         System.out.println("update() is running !");     
  11.     }     
  12.     publicvoid delete(){     
  13.         System.out.println("delete() is running !");     
  14.     }     
  15. }  

    OK,它就是一個javaBean,提供了CRUD方法的javaBean。 
    下面我們建立一個DAO工廠,用來生成DAO例項。

  1. package com.tech.cglibx;  
  2. publicclass BookServiceFactory {  
  3.  privatestatic BookServiceBean service = new BookServiceBean();  
  4.  private BookServiceFactory() {  
  5.  }  
  6.  publicstatic BookServiceBean getInstance() {  
  7.   return service;  
  8.  }  
  9. }  

    接下來我們建立客戶端,用來呼叫CRUD方法。

  1. publicclass Client {     
  2.     publicstaticvoid main(String[] args) {     
  3.         BookServiceBean service = BookServiceFactory.getInstance();   
  4.         doMethod(service);     
  5.     }     
  6.     publicstaticvoid doMethod(BookServiceBean service){     
  7.         service.create();  
  8.         service.update();  
  9.         service.query();  
  10.         service.delete();   
  11.     }     
  12. }   

    OK,完成了,CRUD方法完全被呼叫了。

    當然這裡並沒有CGlib的任何內容。問題不會這麼簡單的就結束,新的需求來臨了。

 
2. one day,Boss告訴我們這些方法不能開放給使用者,只有“boss”才有權使用。怎麼辦,難道我們要在每個方法上面進行判斷嗎?好像這麼做也太那啥了吧?對了,Proxy可能是最好的解決辦法。jdk的代理就可以解決了。 好了我們來動手改造吧。等等jdk的代理需要實現介面,這樣, 我們的dao類需要改變了。既然不想改動dao又要使用代理,我們這就請出CGlib。
我們只需新增一個許可權驗證的方法攔截器。

  1. package com.tech.cglibx;  
  2. import java.lang.reflect.Method;  
  3. import net.sf.cglib.proxy.Enhancer;  
  4. import net.sf.cglib.proxy.MethodInterceptor;  
  5. import net.sf.cglib.proxy.MethodProxy;  
  6. import org.apache.log4j.Logger;  
  7. publicclass MyCglibProxy implements MethodInterceptor{  
  8.  private Logger log=Logger.getLogger(MyCglibProxy.class);  
  9.  public Enhancer enhancer = new Enhancer();  
  10.  private String name;  
  11.  public MyCglibProxy(String name) {  
  12.        this.name = name ;  
  13.  }  
  14.  /** 
  15.   * 根據class物件建立該物件的代理物件 
  16.   * 1、設定父類;2、設定回撥 
  17.   * 本質:動態建立了一個class物件的子類 
  18.   *  
  19.   * @param cls 
  20.   * @return 
  21.   */
  22.  public Object getDaoBean(Class cls) {  
  23.   enhancer.setSuperclass(cls);  
  24.   enhancer.setCallback(this);  
  25.   return enhancer.create();  
  26.  }  
  27.  @Override
  28.  public Object intercept(Object object, Method method, Object[] args,  
  29.    MethodProxy methodProxy) throws Throwable {  
  30.   log.info("呼叫的方法是:" + method.getName());  
  31.   //使用者進行判斷
  32.   if(!"張三".equals(name)){   
  33.    System.out.println("你沒有許可權!");   
  34.    returnnull;   
  35.   }   
  36.   Object result = methodProxy.invokeSuper(object, args);  
  37.   return result;  
  38.  }  
  39. }  

        當然不能忘了對我們的dao工廠進行修改,我們提供一個使用代理的例項生成方法。上面的類中已經提供了一個通用的獲取代理例項的方法,沒有特殊需求(如下3)的方式可以使用上面的方式獲取代理物件。

  1. publicstatic BookServiceBean getProxyInstance(MyCglibProxy myProxy){    
  2.      Enhancer en = new Enhancer();     
  3.      //進行代理   
  4.      en.setSuperclass(BookServiceBean.class);     
  5.      en.setCallback(myProxy);     
  6.      //生成代理例項   
  7.      return (BookServiceBean)en.create();     
  8.  } <span style="font-family: Arial, Verdana, sans-serif; white-space: normal; "> </span>  

     我們這就可以看看客戶端的實現了。添加了兩個方法用來驗證不同使用者的許可權

  1. BookServiceBean service = BookServiceFactory.getProxyInstance(new MyCglibProxy("boss"));  
  2. service.create();  
  3. BookServiceBean service2 = BookServiceFactory.getProxyInstance(new MyCglibProxy("john"));  
  4. service2.create();  

OK,"boss"的正常執行,"john"的沒有執行。 
看到了嗎?簡單的aop就這樣實現了 
難道就這樣結束了麼? 

3.grd Boss又來訓話了,不行不行,現在除了"boss"其他人都用不了了,現在不可以這樣。必須使用開放查詢功能。 
 哈哈,現在可難不倒我們了,因為我們使用了CGlib。當然最簡單的方式是去修改我們的方法攔截器,不過這樣會使邏輯變得複雜,且不利於維護。

還好CGlib給我們提供了方法過濾器(CallbackFilter),CallbackFilte可以明確表明,被代理的類中不同的方法,被哪個攔截器所攔截。

下面我們就來做個過濾器用來過濾query方法。 

  1. package com.tech.cglibx;  
  2. import java.lang.reflect.Method;  
  3. import net.sf.cglib.proxy.CallbackFilter;  
  4. publicclass MyProxyFilter implements

    相關推薦

    java動態代理——JDKCGLIB原理解析使用

    CGLIB的動態代理  原理       代理為控制要訪問的目標物件提供了一種途徑。當訪問物件時,它引入了一個間接的層。JDK自從1.3版本開始,就引入了動態代理,並且經常被用來動態地建立代理。JDK的動態代理用起來非常簡單,當它有一個限制,就是使用動

    Java動態代理(JDK CGLIB、Javassist、ASM之間的差別)

    import com.foo.proxy.Rechargable;   import com.foo.proxy.Vehicle;   import java.lang.reflect.InvocationHandler;   import java.lang.reflect.Method;   im

    Java 靜態代理動態代理的使用及原理解析

    代理模式是軟體開發中常見的設計模式,它的目的是讓呼叫者不用持有具體操作者的引用,而是通過代理者去對具體操作者執行具體的操作。 靜態代理的實現 操作介面: public interface Operate { void doSomething(); } 複製程式碼 操作者: public cla

    java設定模式---代理模式--動態代理模式cglib代理模式詳解

    代理模式使用場景 代理模式的定義:什麼是代理模式呢?代理模式是常用的Java設計模式,它的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理消息等。代理類和委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物

    JDK的Proxy動態代理模式CGLIB動態代理模式的區別共同點

    首先我們來談談聯眾代理模式的不同之處:《1》代理類不同點:(1)Proxy的代理類的建立是通過工具類或者工廠類自動建立的,   我們只需要呼叫Proxy.newProxyInstance(Loader,interfaces,h);正確的傳入相應的引數,就可以得到餓哦們想要的目

    Java動態代理概述手寫實現動態代理

    一:前提 Spring中最重要的兩種思想:控制反轉IOC(Inversion of Control)和麵向切面程式設計AOP(Aspect-Oriented Programming),而AOP最重要的原理就是動態代理,今天我們談一下動態代理。動態代理顧名思義是代替別人做某些

    動態代理(一)java動態代理應用介紹、原理簡介

    java動態代理的應用介紹、原理簡介嘚不嘚概述應用介紹原理介紹 嘚不嘚 好久沒有更新blog了,理論只有應用起來才能有更加深刻的體會。雖然同類的部落格到處都是,但是每個人對同一個技術的理解是不一樣的,每個人注重的細節也不太一樣,不管有沒有人看,寫部落格只是作為個

    Spring的兩種代理JDKCGLIB的區別淺談

    一、原理區別: java動態代理是利用反射機制生成一個實現代理介面的匿名類,在呼叫具體方法前呼叫InvokeHandler來處理。 而cglib動態代理是利用asm開源包,對代理物件類的class檔案

    java代理,靜態代理動態代理以及spring aop代理方式,實現原理統一彙總 Spring中AOP的兩種代理方式(Java動態代理CGLIB代理

    若代理類在程式執行前就已經存在,那麼這種代理方式被成為 靜態代理 ,這種情況下的代理類通常都是我們在Java程式碼中定義的。 通常情況下, 靜態代理中的代理類和委託類會實現同一介面或是派生自相同的父類。 一、概述1. 什麼是代理我們大家都知道微商代理,簡單地說就是代替廠家賣商品,廠家“委託”代理為

    java動態代理JDKCGLIB)筆記

    動態代理:為一堆interface或類的實現提供統一的執行通道,從含義上就像區域網電腦通過代理上網一樣,走統一的通道,代理控制通道,自然可以在通道里加上自定義實現,例如像AOP切面,日誌等。 JDK的動態代理只能對介面實現,代理類需要實現InvocationHandler 介面。 一、介面 pub

    Java動態代理JDK實現CGlib實現

         原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html       一:代理模式(靜態代理)    &nbs

    【轉載】Java動態代理JDK實現CGlib實現(簡單易懂)

          原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html       一:代理模式(靜態代理)           代理模式是常用設計模式的一種,我們在軟體設計時常用的代理一般是指靜態代理,也就是在程式碼中顯式指定的

    java動態代理JDKcglib

    JAVA的動態代理  代理模式  代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本身並不真正實現服務,

    JDKCGLIB動態代理原理

    一 JDK和CGLIB動態代理原理 1、JDK動態代理 利用攔截器(攔截器必須實現InvocationHanlder)加上反射機制生成一個實現代理介面的匿名類, 在呼叫具體方法前呼叫InvokeHandler來處理。 2、CGLiB動態代理 利用ASM開源包,對代理物件類的class檔案載入

    【八】Java設計模式GOF23之動態代理(原生JDKCGLIB

    一、使用JDK原生動態代理 基於Java反射機制。 Java動態代理是基於介面的,如果物件沒有實現介面則選擇用CGLIB方式實現動態代理。 實現步驟: 1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。 2.然後在需要

    Java動態代理JDK介面代理Cglib代理

    代理模式 代理模式是常用的java設計模式,它的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理訊息、過濾訊息、把訊息轉發給委託類,以及事後處理訊息等。代理類與委託類之間通常會存在關聯關係,一個代理類的物件與一個委託類的物件關聯,代理類的物件本身並不真正實現服

    Java動態代理JDK實現CGlib實現(簡單易懂)

    原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html 一:代理模式(靜態代理)           代理模式是常用設計模式的一種,我們在軟體設計時常用的代理一般是指靜態代理,也就是在程式碼中顯式指定的代理。      

    java 動態代理模式(jdkcglib

    ref false spa err ast 反射 步驟 3.1 rate 1 package proxy.dynamicproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.la

    03、動態代理--JDK動態代理CGLib動態代理的組合實例

    listen -- offer pri eth err imp instance music package com.offer.note.Java基礎.動態代理.CGLib引入增強; public interface Browser { void visitI

    JAVA 動態代理原理實現

    ror binary lose ole jdk 動態代理 參數 try lob rac 在 Java 中動態代理和代理都很常見,幾乎是所有主流框架都用到過的知識。在面試中也是經常被提到的話題,於是便總結了本文。 Java動態代理的基本原理為:被代理對象需要實現某個接口(這是