一、首先說一下JDK中的動態代理: JDK中的動態代理是通過反射類Proxy以及InvocationHandler回調介面實現的 但是,JDK中所要進行動態代理的類必須要實現一個介面,也就是說只能對該類所實現介面中定義的方法進行代理,這在實際編程中具有一定的局限性,而且使用反射的效率也並不是很高。 ...
一、首先說一下JDK中的動態代理:
JDK中的動態代理是通過反射類Proxy以及InvocationHandler回調介面實現的
但是,JDK中所要進行動態代理的類必須要實現一個介面,也就是說只能對該類所實現介面中定義的方法進行代理,這在實際編程中具有一定的局限性,而且使用反射的效率也並不是很高。
二、使用CGLib實現:
使用CGLib實現動態代理,完全不受代理類必須實現介面的限制,而且CGLib底層採用ASM位元組碼生成框架,使用位元組碼技術生成代理類,比使用Java反射效率要高。唯一需要註意的是,CGLib不能對聲明為final的方法進行代理,因為CGLib原理是動態生成被代理類的子類。
下麵,將通過一個實例介紹使用CGLib實現動態代理。
1、被代理類:
首先,定義一個類,該類沒有實現任何介面,包含兩個方法。
Java代碼- public class ConcreteClassNoInterface {
- public String getConcreteMethodA(String str){
- System.out.println("ConcreteMethod A ... "+str);
- return str;
- }
- public int getConcreteMethodB(int n){
- System.out.println("ConcreteMethod B ... "+n);
- return n+10;
- }
- }
2、攔截器:
定義一個攔截器。在調用目標方法時,CGLib會回調MethodInterceptor介面方法攔截,來實現你自己的代理邏輯,類似於JDK中的InvocationHandler介面。
Java代碼- public class ConcreteClassInterceptor implements MethodInterceptor{
- public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
- System.out.println("Before:"+method);
- Object object=proxy.invokeSuper(obj, arg);
- System.out.println("After:"+method);
- return object;
- }
- }
參數:Object為由CGLib動態生成的代理類實例,Method為上文中實體類所調用的被代理的方法引用,Object[]為參數值列表,MethodProxy為生成的代理類對方法的代理引用。
返回:從代理實例的方法調用返回的值。
其中,proxy.invokeSuper(obj,arg):
調用代理類實例上的proxy方法的父類方法(即實體類ConcreteClassNoInterface中對應的方法)
在這個示例中,只在調用被代理類方法前後各列印了一句話,當然實際編程中可以是其它複雜邏輯。
3、生成動態代理類:
Java代碼- Enhancer enhancer=new Enhancer();
- enhancer.setSuperclass(ConcreteClassNoInterface.class);
- enhancer.setCallback(new ConcreteClassInterceptor());
- ConcreteClassNoInterface ccni=(ConcreteClassNoInterface)enhancer.create();
這裡Enhancer類是CGLib中的一個位元組碼增強器,它可以方便的對你想要處理的類進行擴展,以後會經常看到它。
首先將被代理類ConcreteClassNoInterface設置成父類,然後設置攔截器ConcreteClassInterceptor,最後執行enhancer.create()動態生成一個代理類,並從Object強制轉型成父類型ConcreteClassNoInterface。
最後,在代理類上調用方法:
Java代碼- ccni.getConcreteMethodA("shensy");
- ccni.getConcreteMethodB(0);
查看控制台輸出:
控制台代碼- Before :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
- ConcreteMethod A ... shensy
- After :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
- Before :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)
- ConcreteMethod B ... 0
- After :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)
可以看到,攔截器在調用被代理類方法前後都執行了print操作。
轉自:http://shensy.iteye.com/blog/1873155