淺談Java代理二:Cglib動態代理-MethodInterceptor
阿新 • • 發佈:2018-11-21
淺談Java代理二:Cglib動態代理-MethodInterceptor
CGLib動態代理特點:
使用CGLib實現動態代理,完全不受代理類必須實現介面的限制,而且CGLib底層採用ASM位元組碼生成框架,使用位元組碼技術生成代理類,比使用Java反射效率要高。唯一需要注意的是,CGLib不能對宣告為final的方法進行代理,因為CGLib原理是動態生成被代理類的子類。
示例業務邏輯:
1-有一個明星叫胡歌(class HuGe)
3-找明星做事情需要經過助理(ProxyFactory )
4-如果要找胡歌唱歌、演戲,需要先找助理,然後助理去找胡歌唱歌、演戲(class testProcyFactory)
1-被代理類(沒有實現任何介面)
package com.huishe.testOfSpring.methodinterceptor; public class HuGe { public void sing(String song) { System.out.println("胡歌演唱: " + song); } public String act(String teleplay) { System.out.println("胡歌決定出演電視劇: " + teleplay);return "胡歌答應出演電視劇: " + teleplay; } }
2-代理工廠(即建立代理的通用寫法)
package com.huishe.testOfSpring.methodinterceptor; 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 ProxyFactory implementsMethodInterceptor{ //要代理的原始物件 private Object object; //1-建立代理物件 public Object createProcy(Object target){ this.object = target; //1-Enhancer類是CGLib中的一個位元組碼增強器,它可以方便的對你想要處理的類進行擴充套件 Enhancer enhancer=new Enhancer(); //2-將被代理類HuGe設定成父類 enhancer.setSuperclass(this.object.getClass()); //3-設定攔截器 enhancer.setCallback(this); //4-動態生成一個代理類 Object objProxy = enhancer.create(); return objProxy; } //2-實現MethodInterceptor的intercept方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before: " + method); //呼叫proxy.invoke()方法,會報java.lang.StackOverflowError錯誤,原因是invoke()內部會一直被反覆呼叫 //Object object = proxy.invoke(obj, args); Object object = proxy.invokeSuper(obj, args); System.out.println("after: " + method); return object; } }
3-進行測試
package com.huishe.testOfSpring.methodinterceptor; import org.junit.Test; import net.sf.cglib.proxy.Enhancer; public class cglibMethodInterceptorTest { @Test public void testProcyFactory(){ //1-例項化需要被代理的類 HuGe huGe = new HuGe(); //2-例項化代理工廠 ProxyFactory cglibProxy = new ProxyFactory(); //3-動態生成一個代理類,並從Object強制轉型成父型別HuGe HuGe hg =(HuGe)cglibProxy.createProcy(huGe); //4-執行動態代理類的方法 hg.sing("逍遙嘆"); hg.act("琅琊榜"); } }
4-測試結果
日誌輸出: before: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String) 胡歌演唱: 逍遙嘆 after: public void com.huishe.testOfSpring.methodinterceptor.HuGe.sing(java.lang.String) before: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String) 胡歌決定出演電視劇: 琅琊榜 after: public java.lang.String com.huishe.testOfSpring.methodinterceptor.HuGe.act(java.lang.String)
參考資料
1-https://blog.csdn.net/jiaotuwoaini/article/details/51675684
2-https://www.cnblogs.com/writeLessDoMore/p/6973853.html