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)的基礎,所以,瞭解動態代理的實現方法和機制是很有必要的,通過一個簡單的例項,可以對動態代理有初步的認識,為以後的深入學習打下基礎。