1. 程式人生 > >Cglib方法實現動態代理

Cglib方法實現動態代理

  除了使用JDK方式產生動態代理外,Java還給我們提供了另外一種產生動態代理的方法,那就是使用cglib。

  cglib是這樣實現動態代理的:

  · ①.針對類來實現代理

  · ②對指定目標類產生一個子類 ,通過方法攔截技術攔截所有父類方法的呼叫。

  ·

  cglib的實現機制與Java 動態代理不同,它是通過繼承實現的 ,它也是動態建立了一個類,但這個類的父類是被代理的類,代理類重寫了父類的所有public非final方法,改為呼叫Callback中的相關方法,在本例中,呼叫CglibProxy的intercept方法。

  具體實現步驟如下:

  1.我們先新建一個普通的Java專案,然後,在使用這個方法之前,我們需要給專案匯入所需的jar包。

  cglib-nodep-2.2.jar

  2.建立被代理類

  package cglibProxy;

  public class Person {

  public void work(){

  System.out.println(工作中..);

  }

  }

  簡單起見,我們這裡只給Person類實現一個work()方法,用於模擬業務實現。

  3.接下來就是最重要的一點,建立代理類,代理類需要實現以下介面:

  interface MethodInterceptor{}

  這個介面需要我們匯入jar包後才會出現,顧名思義,也就是方法攔截器。

  代理類的實現細節如下:

  package cglibProxy;

  import java.lang.reflect.Method;

  import net.sf.cglib.proxy.Enhancer;

  import net.sf.cglib.proxy.MethodInterceptor;

  import net.sf.cglib.proxy.MethodProxy;

  public class CglibProxy implements MethodInterceptor {

  private Enhancer enhancer = new Enhancer();

  public Object getProxy(Class clazz){

  //設定建立子類的類,即指定為哪個類產生代理類

  enhancer.setSuperclass(clazz);

  /*設定回撥函式

  * setCallback設定被代理類的public非final方法被呼叫時的處理類

  * 這個例子中我們設定的方法為Person中的work()方法

  * 當work()方法被呼叫時,由該類進行處理

  * */

  enhancer.setCallback(this);

  //建立子類例項

  return enhancer.create();

  }

  /*

  * 作用:攔截所有目標類方法的呼叫

  * 引數:

  * 1. obj --目標類的例項物件

  * 2. method--目標方法的反射物件

  * 3. args --方法的引數

  * 4. proxy --代理類的例項物件

  * */

  @Override

  public Object intercept(Object obj, Method method, Object[] args,

  MethodProxy proxy) throws Throwable {

  System.out.println(代理類開始介入..);

  //代理類呼叫父類的方法

  proxy.invokeSuper(obj, args);

  System.out.println(代理類介入結束);

  return null;

  }

  }

  這裡出現了一個比較少見的類Enhancer,查閱官方API,有這麼一段註解:

  /*Generates dynamic subclasses to enable method interception.

  This class started as a substitute for the standard Dynamic Proxy

  support included with JDK 1.3, but one that allowed the proxies

  interfaces. The dynamically generated subclasses override

  the non-final methods of the superclass and have hooks which

  callback to user-defined interceptor implementations.*/

  翻譯過來大概意思就是:

  /*生成動態子類以啟用方法攔截。

  這個類開始替代了JDK 1.3中包含的標準動態代理支援,

  但是允許代理擴充套件一個具體的基類,以及實現介面。

  動態生成的子類覆蓋超類的非最終方法,

  並具有回撥到使用者定義的攔截器實現的鉤子。*/

  其實Enhancer類是CGLib中的一個位元組碼增強器,它可以方便的對你想要處理的類進行擴充套件。

  我們通過在代理類中聚合一個Enhancer類的一個例項物件,然後呼叫Enhancer例項物件的相應方法,對父類的呼叫方法進行攔截。

  代理類返回代理物件由getProxy()方法實現,其中:

  enhancer.setSuperclass(clazz);

  /*官方API對該類的註解如下:

  *Set the class which the generated class will extend.

  *翻譯:

  *設定生成的類將要繼承的類

  *這樣比較難懂,從方法名中我們可以看出,這其實就是設定代理類的父類

  */

  與JDK動態代理不同,CglibProxy中沒有被代理的物件,它通過MethodProxy類的例項物件proxy的invokeSuper方法呼叫被代理類的方法:

  proxy.invokeSuper(obj, args);

  但是,要注意的是,它不能這樣呼叫被代理類的方法:

  proxy.invoke(obj, args);

  因為proxy是代理物件,呼叫這個方法還會呼叫到CglibProxy的intercept方法,造成死迴圈。

  3.最後,我們建立測試類

  package cglibProxy;

  public class Test {

  public static void main(String[] args) {

  //在main方法中,沒有建立被代理的物件,建立的物件直接就是代理物件。

  CglibProxy proxy = new CglibProxy();

  //getProxy()方法返回代理方法產生的例項物件

  Person person = (Person)proxy.getProxy(Person.class);

  //代理物件呼叫wokr()方法

  person.work();

  }

  }

  執行結果:

  代理類開始介入..

  工作中..

  代理類介入結束

  動態代理是實現面向切面的程式設計(AOP – Aspect Oriented Programming)的基礎,所以,瞭解動態代理的實現方法和機制是很有必要的,通過一個簡單的例項,可以對動態代理有初步的認識,為以後的深入學習打下基礎。