您好,登錄后才能下訂單哦!
Java中Cglib動態代理是什么?這個問題可能是我們日常學習或工作經常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家帶來的參考內容,讓我們一起來看看吧!
什么是Cglib動態代理?
我們先回顧一下上一篇的jdk動態代理,jdk動態代理是通過接口來在運行時動態創建委托類的代理對象,但是跟靜態代理一樣有一個缺點,就是必須和委托類實現相同的接口,當接口數量增加時,便需要增加代理類的數量才能滿足需求,而且如果委托類是別人寫的,而且沒有實現任何接口,那么jdk動態代理就有些力不從心了。
這時候Cglib動態代理就脫穎而出了,Cglib并不依賴接口,可以直接生成委托類的代理對象,而且可以代理委托類的任意非final修飾的public和protected方法,我們可以先來看一個栗子。
先定義一個Programmer類:
public class Programmer { private String name; public void setName(String name) { System.out.println("Setting Name."); this.name = name; }public void code(){ System.out.println(name + " is writing bugs."); } }
然后定義一個代理類:
public class ProgrammerProxy implements MethodInterceptor { /** * 內部持有委托類對象的引用 */ private Object target; /** * 創建代理類對象 */ public Programmer createProxy(Programmer object){ target = object; //創建Enhancer對象 Enhancer enhancer = new Enhancer(); //設置要代理的目標類,以擴展功能 enhancer.setSuperclass(this.target.getClass()); //設置單一回調對象,在回調中攔截對目標方法的調用 enhancer.setCallback(this); //設置類加載器 enhancer.setClassLoader(object.getClass().getClassLoader()); //創建代理對象 return (Programmer)enhancer.create(); } /** * 回調方法:在代理實例上攔截并處理目標方法的調用,返回結果 * @param proxy 代理類 * @param method 被代理的方法 * @param params 該方法的參數數組 * @param methodProxy */ @Override public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable { //調用之前處理 doBefore(); //調用原方法 method.invoke(target,params); //調用之后處理 doAfter(); return null; } private void doAfter() { System.out.println("do after."); } private void doBefore() { System.out.println("do before."); } }
然后測試一下:
public class ProxyTest { @Test public void testCglibProxy(){ //創建一個Programmer對象 Programmer programmerA = new Programmer(); programmerA.setName("Frank"); //創建代理對象 Programmer programmerProxyA = new ProgrammerProxy().createProxy(programmerA); programmerProxyA.code(); //修改代理對象 programmerProxyA.setName("Wang"); programmerProxyA.code(); //修改委托類對象 programmerA.setName("Song"); programmerProxyA.code(); } }
輸出如下:
Setting Name.
do before.
Frank is writing bugs.
do after.
do before.
Setting Name.
do after.
do before.
Wang is writing bugs.
do after.
Setting Name.
do before.
Song is writing bugs.
do after.
Cglib實現動態代理的步驟也不是很麻煩,先創建一個類實現MethodInterceptor接口,重寫intercept方法,在intercep中可以截獲委托類的所有非final修飾的public和protected方法,上例中,method.invoke(target,params);即為調用原對象的原方法,在代理類中保存了委托類對象的引用,這一點跟JDK動態代理是一樣的。在調用原方法前先調用了doBefore方法,調用之后還調用了doAfter方法,從而實現了代理功能。至于createProxy方法,也只是一個固定步驟,先創建Enhance對象,然后將委托類的一些屬性往里塞,然后調用create方法來動態生成代理對象。
在測試類中,為了更明顯的說明代理類與委托類的關系,分別用代理類對象programmerProxyA和委托類對象programmerA對name字段進行修改,可以產生一樣的效果。
下面來對比一下Cglib動態代理與JDK動態代理:
1.兩者都是動態代理,都是運行時動態生成代理對象。
2.JDK動態代理利用的是接口信息來實現的代理,委托類必須實現某個或者某些接口,而Cglib則是利用繼承關系,利用asm在運行時動態生成委托類的子類,從而實現對委托類的代理。因此不依賴接口。
3.Cglib由于是利用繼承關系來實現代理的,因此無法代理被final修飾的類以及被final修飾的方法。
4.Cglib一般來說效率要比JDK動態代理效率更高,可以實現的代理也更為強大。
當然,具體情況具體分析,雖然Cglib比Jdk動態代理更強大,但并不一定各個地方都強行使用,有時候JDK動態代理相對來說更加簡單粗暴。
感謝各位的閱讀!看完上述內容,你們對Java中Cglib動態代理是什么大概了解了嗎?希望文章內容對大家有所幫助。如果想了解更多相關文章內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。