yuyee

          cglib入門

          代理為要控制訪問的類提供了一種可行的途徑,他為目標類引入一個中間層,JDK1.3后也有動態代理,不過性能不是很好,1.6有所加強。
          CGLIB是一個強大的代碼生成包,在ASM上建立,在一些開源工具中經常可以看到他的身影,比如hibernate,spring。
          CGLIB底層通過字節碼處理框架ASM來將字節碼生成新的類,在spring AOP中不強制使用CGLIB,默認是JDK動態代理。
          CGLIB 包情況:
          net.sf.cglib.core:底層字節碼處理類,大部分與ASM有關。
          net.sf.cglib.transform:編譯期或運行期和類文件的轉換
          net.sf.cglib.proxy:實現創建代理和方法攔截器的類
          net.sf.cglib.reflect:實現快速放射
          net.sf.cglib.util:工具包
          net.sf.cglib.beans:javabean相關工具類
          通過CGLIB創建動態代理,本質上,他是動態的生成目標類的子類,覆蓋目標類所有不是final的方法,并給他們設置好callback,因此,原有類的每個方法調用就會變成自定義的攔截方法。
          創建動態代理時通常要用到如下api:net.sf.cglib.proxy.Callback這個接口,他是很關鍵的一個接口,所有被net.sf.cglib.proxy.Enhancer類調用的回調借口都要繼承這個接口
          如:public interface MethodInterceptor
          extends Callback
          {
              /**
               * All generated proxied methods call this method instead of the original method.
               * The original method may either be invoked by normal reflection using the Method object,
               * or by using the MethodProxy (faster).
               * @param obj "this", the enhanced object
               * @param method intercepted Method
               * @param args argument array; primitive types are wrapped
               * @param proxy used to invoke super (non-intercepted method); may be called
               * as many times as needed
               * @throws Throwable any exception may be thrown; if so, super method will not be invoked
               * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
               * @see MethodProxy
               */    
              public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
                                         MethodProxy proxy) throws Throwable;

          }
          這個是基與方法的回調,第一個參數是代理對象,第二個是被攔截的方法對象,第三個是方法參數,第四個是方法的代理對象。
          public class MyClass {
          public void method1() {
          System.out.println("method1");
          }

          public void method2() {
          System.out.println("method2");
          }
          }
          攔截器:
          public class MethodInterceptImpl implements MethodInterceptor {

          public Object intercept(Object arg0, Method arg1, Object[] arg2,
          MethodProxy arg3) throws Throwable {
          System.out.println(arg1.getName()+"--intercept");
          arg3.invokeSuper(arg0, arg2);// 這里其實也可以用原來的方法對象來執行,但是性能上不如cglib的方法代理類
          return null;
          }
          public class MainTest {
          public static void main(String[] args) {
          simpleTest();
          }

          private static void simpleTest() {
          Enhancer en = new Enhancer();
          en.setCallback(new MethodInterceptImpl());
          en.setSuperclass(MyClass.class);
          MyClass m = (MyClass) en.create();
          m.method1();
          m.method2();
          }
          結果:method1--intercept
          method1
          method2--intercept
          method2
          現實項目中可能存在某些需求,比如method1需要攔截,而method2不需要攔截。那我們可以對callback做下選擇,使用net.sf.cglib.proxy.CallbackFilter做一些過濾。
          public class MethodFilterImpl implements CallbackFilter {

          private final static int execute = 0;
          private final static int unexecute = 1;

          public int accept(Method method) {
          String methodName = method.getName();
          if("method1".equals(methodName)){
          return execute;
          }
          return unexecute;
          }

          }

          調用的時候需要給callback設置好索引位置,因為accept的返回值就是callbacks數組的索引位置。
          private static void filterTest() {
          Enhancer en = new Enhancer();
          Callback[] callbacks = new Callback[] { new MethodInterceptImpl(),
          NoOp.INSTANCE };//這里攔截器的索引位置要與filter里的設置一致
          en.setCallbacks(callbacks);
          en.setSuperclass(MyClass.class);
          en.setCallbackFilter(new MethodFilterImpl());
          MyClass m = (MyClass) en.create();
          m.method1();
          m.method2();
          }
          這里callbacks[1]這個位置使用了NoOp這個回調接口
          public interface NoOp extends Callback
          {
              /**
               * A thread-safe singleton instance of the <code>NoOp</code> callback.
               */
              public static final NoOp INSTANCE = new NoOp() { };
          }
          這個callback其實就是直接把任務委派給這個方法在父類中的實現,其實也等同于沒做什么額外的事情
          執行結果:method1--intercept
          method1
          method2
          method2 并未被MethodInterceptImpl攔截

          }

          posted on 2010-10-26 14:27 羔羊 閱讀(1042) 評論(1)  編輯  收藏 所屬分類: aop

          Feedback

          # re: cglib入門[未登錄] 2011-09-03 12:00 小白

          小白到此一游  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 资源县| 丰镇市| 休宁县| 铅山县| 阿瓦提县| 称多县| 河南省| 林甸县| 英吉沙县| 新建县| 清镇市| 临潭县| 镇坪县| 大理市| 苍梧县| 渑池县| 茶陵县| 乐安县| 河曲县| 焉耆| 湖州市| 常山县| 博湖县| 黑水县| 周宁县| 乳源| 晋宁县| 杨浦区| 县级市| 神农架林区| 金乡县| 白山市| 荆州市| 兰坪| 神池县| 泰兴市| 丰都县| 得荣县| 绥德县| 峨眉山市| 略阳县|