CGLib動態代理(轉載)

實戰CGLib系列文章

本篇介紹通過MethodInterceptor和Enhancer實現一個動態代理。

一、首先說一下JDK中的動態代理

JDK中的動態代理是通過反射類Proxy以及InvocationHandler回調接口實現的,不瞭解的同學請參考我的這篇Blog:Java動態代理詳解 http://shensy.iteye.com/blog/1698197 

但是,JDK中所要進行動態代理的類必須要實現一個接口,也就是說只能對該類所實現接口中定義的方法進行代理,這在實際編程中具有一定的侷限性,而且使用反射的效率也並不是很高。

二、使用CGLib實現

使用CGLib實現動態代理,完全不受代理類必須實現接口的限制,而且CGLib底層採用ASM字節碼生成框架,使用字節碼技術生成代理類,比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明爲final的方法進行代理,因爲CGLib原理是動態生成被代理類的子類。

下面,將通過一個實例介紹使用CGLib實現動態代理。

1、被代理類

首先,定義一個類,該類沒有實現任何接口,包含兩個方法。

Java代碼  收藏代碼
  1. public class ConcreteClassNoInterface {  
  2.     public String getConcreteMethodA(String str){  
  3.         System.out.println("ConcreteMethod A ... "+str);  
  4.         return str;  
  5.     }  
  6.     public int getConcreteMethodB(int n){  
  7.         System.out.println("ConcreteMethod B ... "+n);  
  8.         return n+10;  
  9.     }  
  10. }  

2、攔截器

定義一個攔截器。在調用目標方法時,CGLib會回調MethodInterceptor接口方法攔截,來實現你自己的代理邏輯,類似於JDK中的InvocationHandler接口。

Java代碼  收藏代碼
  1. public class ConcreteClassInterceptor implements MethodInterceptor{  
  2.     public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {  
  3.         System.out.println("Before:"+method);    
  4.         Object object=proxy.invokeSuper(obj, arg);  
  5.         System.out.println("After:"+method);   
  6.         return object;  
  7.     }  
  8. }  

參數:Object爲由CGLib動態生成的代理類實例,Method爲上文中實體類所調用的被代理的方法引用,Object[]爲參數值列表,MethodProxy爲生成的代理類對方法的代理引用。

返回:從代理實例的方法調用返回的值。

其中,proxy.invokeSuper(obj,arg):

調用代理類實例上的proxy方法的父類方法(即實體類ConcreteClassNoInterface中對應的方法)

在這個示例中,只在調用被代理類方法前後各打印了一句話,當然實際編程中可以是其它複雜邏輯。

3、生成動態代理類

Java代碼  收藏代碼
  1. Enhancer enhancer=new Enhancer();  
  2. enhancer.setSuperclass(ConcreteClassNoInterface.class);  
  3. enhancer.setCallback(new ConcreteClassInterceptor());  
  4. ConcreteClassNoInterface ccni=(ConcreteClassNoInterface)enhancer.create();  

這裏Enhancer類是CGLib中的一個字節碼增強器,它可以方便的對你想要處理的類進行擴展,以後會經常看到它。

首先將被代理類ConcreteClassNoInterface設置成父類,然後設置攔截器ConcreteClassInterceptor,最後執行enhancer.create()動態生成一個代理類,並從Object強制轉型成父類型ConcreteClassNoInterface。

最後,在代理類上調用方法:

Java代碼  收藏代碼
  1. ccni.getConcreteMethodA("shensy");  
  2. ccni.getConcreteMethodB(0);  

查看控制檯輸出:

控制檯代碼  收藏代碼
  1. Before :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)  
  2. ConcreteMethod A ... shensy  
  3. After :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)  
  4. Before :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)  
  5. ConcreteMethod B ... 0  
  6. After :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)  

可以看到,攔截器在調用被代理類方法前後都執行了print操作。

 

結束語

以上就是CGLib實現動態代理的一個示例,本系列後面將繼續介紹CGLib的強大功能,敬請期待。


聲明: 轉載自 http://shensy.iteye.com/blog/1873155

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章