stone2083

          CGlib簡單介紹

          CGlib概述:
          cglib(Code Generation Library)是一個強大的,高性能,高質量的Code生成類庫。它可以在運行期擴展Java類與實現(xiàn)Java接口。
          cglib封裝了asm,可以在運行期動態(tài)生成新的class。
          cglib用于AOP,jdk中的proxy必須基于接口,cglib卻沒有這個限制。

          CGlib應用:
          以一個實例在簡單介紹下cglib的應用。
          我們模擬一個虛擬的場景,關于信息的管理。

          1)原始需求是任何人可以操作信息的create,update,delete,query操作。
          InfoManager.java--封裝對信息的操作
          public class InfoManager {
              
          // 模擬查詢操作
              public void query() {
                  System.out.println(
          "query");
              }
              
          // 模擬創(chuàng)建操作
              public void create() {
                  System.out.println(
          "create");
              }
              
          // 模擬更新操作
              public void update() {
                  System.out.println(
          "update");
              }
              
          // 模擬刪除操作
              public void delete() {
                  System.out.println(
          "delete");
              }
          }
          InfoManagerFactory.java--工廠類
          public class InfoManagerFactory {
              
          private static InfoManager manger = new InfoManager();
              
          /**
               * 創(chuàng)建原始的InfoManager
               * 
               * 
          @return
               
          */
              
          public static InfoManager getInstance() {
                  
          return manger;
              }
          }
          client.java--供客戶端調用
          public class Client {

              
          public static void main(String[] args) {
                  Client c 
          = new Client();
                  c.anyonecanManager();
              }

              
          /**
               * 模擬:沒有任何權限要求,任何人都可以操作
               
          */
              
          public void anyonecanManager() {
                  System.out.println(
          "any one can do manager");
                  InfoManager manager 
          = InfoManagerFactory.getInstance();
                  doCRUD(manager);
                  separatorLine();
              }

              
          /**
               * 對Info做增加/更新/刪除/查詢操作
               * 
               * 
          @param manager
               
          */
              
          private void doCRUD(InfoManager manager) {
                  manager.create();
                  manager.update();
                  manager.delete();
                  manager.query();
              }

              
          /**
               * 加一個分隔行,用于區(qū)分
               
          */
              
          private void separatorLine() {
                  System.out.println(
          "################################");
              }

          }
          至此,沒有涉及到cglib的內容,因為需求太簡單了,但是接下來,需求發(fā)生了改變,要求:

          2)只有一個叫“maurice”的用戶登錄,才允許對信息進行create,update,delete,query的操作。
          怎么辦?難道在每個方法前,都加上一個權限判斷嗎?這樣重復邏輯太多了,于是乎想到了Proxy(代理模式),但是原先的InfoManager也沒有實現(xiàn)接口,不能采用jdk的proxy。那么cglib在這邊就要隆重登場。
          一旦使用cgblig,只需要添加一個MethodInterceptor的類以及修改factory代碼就可以實現(xiàn)這個需求。
          AuthProxy.java--權限校驗代理類
          public class AuthProxy implements MethodInterceptor {

              
          private String name; // 會員登錄名

              
          public AuthProxy(String name) {
                  
          this.name = name;
              }

              
          /**
               * 權限校驗,如果會員名為:maurice,則有權限做操作,否則提示沒有權限
               
          */
              @Override
              
          public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                  
          if (!"maurice".equals(this.name)) {
                      System.out.println(
          "AuthProxy:you have no permits to do manager!");
                      
          return null;
                  }
                  
          return proxy.invokeSuper(obj, args);
              }

              
          public String getName() {
                  
          return name;
              }

              
          public void setName(String name) {
                  
          this.name = name;
              }

          }
          InfoManagerFactory.java--代碼變動如下:
          public class InfoManagerFactory {

              
          /**
               * 創(chuàng)建帶有權限檢驗的InfoManager
               * 
               * 
          @param auth
               * 
          @return
               
          */
              
          public static InfoManager getAuthInstance(AuthProxy auth) {
                  Enhancer enhancer 
          = new Enhancer();
                  enhancer.setSuperclass(InfoManager.
          class);
                  enhancer.setCallback(auth);
                  
          return (InfoManager) enhancer.create();
              }

              
          }
          client.java--代碼修改如下
          public class Client {

              
          public static void main(String[] args) {
                  Client c 
          = new Client();
                  c.haveNoAuthManager();
                  c.haveAuthManager();
              }

              
          /**
               * 模擬:登錄會員沒有權限
               
          */
              
          public void haveNoAuthManager() {
                  System.out.println(
          "the loginer's name is not maurice,so have no permits do manager");
                  InfoManager noAuthManager 
          = InfoManagerFactory.getAuthInstance(new AuthProxy("maurice1"));
                  doCRUD(noAuthManager);
                  separatorLine();
              }

              
          /**
               * 模擬:登錄會員有權限
               
          */
              
          public void haveAuthManager() {
                  System.out.println(
          "the loginer's name is maurice,so have permits do manager");
                  InfoManager authManager 
          = InfoManagerFactory.getAuthInstance(new AuthProxy("maurice"));
                  doCRUD(authManager);
                  separatorLine();
              }

              
          /**
               * 對Info做增加/更新/刪除/查詢操作
               * 
               * 
          @param manager
               
          */
              
          private void doCRUD(InfoManager manager) {
                  manager.create();
                  manager.update();
                  manager.delete();
                  manager.query();
              }

              
          /**
               * 加一個分隔行,用于區(qū)分
               
          */
              
          private void separatorLine() {
                  System.out.println(
          "################################");
              }

          }
          執(zhí)行下代碼,發(fā)現(xiàn)這時client端中已經加上了權限校驗。
          同樣是InfoManager,為什么這時能多了權限的判斷呢?Factory中enhancer.create()返回的到底是什么對象呢?這個疑問將在第三部分CGlib中解釋。
          這邊的代碼,其實是介紹了cglib中的enhancer功能.

          到這里,參照上面的代碼,就可以使用cglib帶來的aop功能了。但是為了更多介紹下cglib的功能,模擬需求再次發(fā)生變化:

          3)由于query功能用戶maurice才能使用,招來其他用戶的強烈的抱怨,所以權限再次變更,只有create,update,delete,才需要權限保護,query任何人都可以使用。
          怎么辦?采用AuthProxy,使得InfoManager中的所有方法都被代理,加上了權限的判斷。當然,最容易想到的辦法,就是在AuthProxy的intercept的方法中再做下判斷,如果代理的method是query,不需要權限驗證。這么做,可以,但是一旦邏輯比較復雜的時候,intercept這個方法要做的事情會很多,邏輯會異常的復雜。
          幸好,cglib還提供了CallbackFilter。使用CallbackFilter,可以明確表明,被代理的類(InfoManager)中不同的方法,被哪個攔截器(interceptor)攔截。
          AuthProxyFilter.java
          public class AuthProxyFilter implements CallbackFilter {

              
          private static final int AUTH_NEED     = 0;
              
          private static final int AUTH_NOT_NEED = 1;

              
          /**
               * <pre>
               * 選擇使用的proxy
               * 如果調用query函數(shù),則使用第二個proxy
               * 否則,使用第一個proxy
               * </pre>
               
          */
              @Override
              
          public int accept(Method method) {
                  
          if ("query".equals(method.getName())) {
                      
          return AUTH_NOT_NEED;
                  }
                  
          return AUTH_NEED;
              }

          }
          這段代碼什么意思?其中的accept方法的意思是說,如果代理的方法是query(),那么使用第二個攔截器去攔截,如果代理的方法不是query(),那么使用第一個攔截器去攔截。所以我們只要再寫一個攔截器,不做權限校驗就行了。(其實,cglib中的NoOp.INSTANCE就是一個空的攔截器,只要配置上這個就可以了。)
          InfoManagerFactory.java--代碼修改如下:(配置不同的攔截器和filter)
          public class InfoManagerFactory {

              
          /**
               * 創(chuàng)建不同權限要求的InfoManager
               * 
               * 
          @param auth
               * 
          @return
               
          */
              
          public static InfoManager getSelectivityAuthInstance(AuthProxy auth) {
                  Enhancer enhancer 
          = new Enhancer();
                  enhancer.setSuperclass(InfoManager.
          class);
                  enhancer.setCallbacks(
          new Callback[] { auth, NoOp.INSTANCE });
                  enhancer.setCallbackFilter(
          new AuthProxyFilter());
                  
          return (InfoManager) enhancer.create();
              }

          }
          記住:setCallbacks中的攔截器(interceptor)的順序,一定要和CallbackFilter里面指定的順序一致!!切忌。

          Client.java
          public class Client {

              
          public static void main(String[] args) {
                  Client c 
          = new Client();
                  c.selectivityAuthManager();
              }
              
              
          /**
               * 模擬:沒有權限的會員,可以作查詢操作
               
          */
              
          public void selectivityAuthManager() {
                  System.out.println(
          "the loginer's name is not maurice,so have no permits do manager except do query operator");
                  InfoManager authManager 
          = InfoManagerFactory.getSelectivityAuthInstance(new AuthProxy("maurice1"));
                  doCRUD(authManager);
                  separatorLine();
              }

              
          /**
               * 對Info做增加/更新/刪除/查詢操作
               * 
               * 
          @param manager
               
          */
              
          private void doCRUD(InfoManager manager) {
                  manager.create();
                  manager.update();
                  manager.delete();
                  manager.query();
              }

              
          /**
               * 加一個分隔行,用于區(qū)分
               
          */
              
          private void separatorLine() {
                  System.out.println(
          "################################");
              }

          }
          此時,對于query的權限校驗已經被去掉了。


          通過一個模擬需求,簡單介紹了cglib aop功能的使用。
          CGlib應用非常廣,在spring,hibernate等框架中,被大量的使用。


          CGlib原理:
          cglib神奇嗎?其實一旦了解cglib enhancer的原理,一切就真相大白了。
          剛才在第二部分中,有個疑問:enhancer.create()到底返回了什么對象?

          其實在剛才的例子中,cglib在代碼運行期,動態(tài)生成了InfoManager的子類,并且根據(jù)CallbackFilter的accept方法,覆寫了InfoManager中的所有方法--去執(zhí)行相應的MethodInterceptor的intercept方法。

          有興趣的朋友可以看看我反編譯的InfoManager的子類,就可以很明白知道具體的實現(xiàn)了。(需要有耐心才可以)
          InfoManager$$EnhancerByCGLIB$$de624598.jad
          // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
          // Jad home page: http://www.geocities.com/kpdus/jad.html
          // Decompiler options: packimports(3) 
          // Source File Name:   <generated>

          package cn.eulic.codelab.cglib;

          import java.lang.reflect.Method;
          import net.sf.cglib.core.Signature;
          import net.sf.cglib.proxy.*;

          // Referenced classes of package cn.eulic.codelab.cglib:
          //            InfoManager

          public class CGLIB.BIND_CALLBACKS extends InfoManager
              
          implements Factory
          {

              
          static void CGLIB$STATICHOOK1()
              {
                  Class class1;
                  ClassLoader classloader;
                  CGLIB$THREAD_CALLBACKS 
          = new ThreadLocal();
                  classloader 
          = (class1 = Class.forName("cn.eulic.codelab.cglib.InfoManager$$EnhancerByCGLIB$$de624598")).getClassLoader();
                  classloader;
                  CGLIB$emptyArgs 
          = new Object[0];
                  CGLIB$delete$
          0$Proxy = MethodProxy.create(classloader, (CGLIB$delete$0$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("delete"new Class[0])).getDeclaringClass(), class1, "()V""delete""CGLIB$delete$0");
                  CGLIB$create$
          1$Proxy = MethodProxy.create(classloader, (CGLIB$create$1$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("create"new Class[0])).getDeclaringClass(), class1, "()V""create""CGLIB$create$1");
                  CGLIB$query$
          2$Proxy = MethodProxy.create(classloader, (CGLIB$query$2$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("query"new Class[0])).getDeclaringClass(), class1, "()V""query""CGLIB$query$2");
                  CGLIB$update$
          3$Proxy = MethodProxy.create(classloader, (CGLIB$update$3$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("update"new Class[0])).getDeclaringClass(), class1, "()V""update""CGLIB$update$3");
                  CGLIB$finalize$
          4$Proxy = MethodProxy.create(classloader, (CGLIB$finalize$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize"new Class[0])).getDeclaringClass(), class1, "()V""finalize""CGLIB$finalize$4");
                  CGLIB$hashCode$
          5$Proxy = MethodProxy.create(classloader, (CGLIB$hashCode$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode"new Class[0])).getDeclaringClass(), class1, "()I""hashCode""CGLIB$hashCode$5");
                  CGLIB$clone$
          6$Proxy = MethodProxy.create(classloader, (CGLIB$clone$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone"new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/Object;""clone""CGLIB$clone$6");
                  CGLIB$equals$
          7$Proxy = MethodProxy.create(classloader, (CGLIB$equals$7$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals"new Class[] {
                      Class.forName(
          "java.lang.Object")
                  })).getDeclaringClass(), class1, 
          "(Ljava/lang/Object;)Z""equals""CGLIB$equals$7");
                  CGLIB$toString$
          8$Proxy = MethodProxy.create(classloader, (CGLIB$toString$8$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString"new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/String;""toString""CGLIB$toString$8");
                  
          return;
              }

              
          final void CGLIB$delete$0()
              {
                  
          super.delete();
              }

              
          public final void delete()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          break MISSING_BLOCK_LABEL_21;
          _L4:
                  
          break MISSING_BLOCK_LABEL_37;
                  
          this;
                  CGLIB$delete$
          0$Method;
                  CGLIB$emptyArgs;
                  CGLIB$delete$
          0$Proxy;
                  intercept();
                  
          return;
                  
          super.delete();
                  
          return;
              }

              
          final void CGLIB$create$1()
              {
                  
          super.create();
              }

              
          public final void create()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          break MISSING_BLOCK_LABEL_21;
          _L4:
                  
          break MISSING_BLOCK_LABEL_37;
                  
          this;
                  CGLIB$create$
          1$Method;
                  CGLIB$emptyArgs;
                  CGLIB$create$
          1$Proxy;
                  intercept();
                  
          return;
                  
          super.create();
                  
          return;
              }

              
          final void CGLIB$query$2()
              {
                  
          super.query();
              }

              
          public final void query()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          break MISSING_BLOCK_LABEL_21;
          _L4:
                  
          break MISSING_BLOCK_LABEL_37;
                  
          this;
                  CGLIB$query$
          2$Method;
                  CGLIB$emptyArgs;
                  CGLIB$query$
          2$Proxy;
                  intercept();
                  
          return;
                  
          super.query();
                  
          return;
              }

              
          final void CGLIB$update$3()
              {
                  
          super.update();
              }

              
          public final void update()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          break MISSING_BLOCK_LABEL_21;
          _L4:
                  
          break MISSING_BLOCK_LABEL_37;
                  
          this;
                  CGLIB$update$
          3$Method;
                  CGLIB$emptyArgs;
                  CGLIB$update$
          3$Proxy;
                  intercept();
                  
          return;
                  
          super.update();
                  
          return;
              }

              
          final void CGLIB$finalize$4()
                  
          throws Throwable
              {
                  
          super.finalize();
              }

              
          protected final void finalize()
                  
          throws Throwable
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          break MISSING_BLOCK_LABEL_21;
          _L4:
                  
          break MISSING_BLOCK_LABEL_37;
                  
          this;
                  CGLIB$finalize$
          4$Method;
                  CGLIB$emptyArgs;
                  CGLIB$finalize$
          4$Proxy;
                  intercept();
                  
          return;
                  
          super.finalize();
                  
          return;
              }

              
          final int CGLIB$hashCode$5()
              {
                  
          return super.hashCode();
              }

              
          public final int hashCode()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          52;
                     
          goto _L3 _L4
          _L3:
                  
          this;
                  CGLIB$hashCode$
          5$Method;
                  CGLIB$emptyArgs;
                  CGLIB$hashCode$
          5$Proxy;
                  intercept();
                  JVM INSTR dup ;
                  JVM INSTR ifnonnull 
          45;
                     
          goto _L5 _L6
          _L5:
                  JVM INSTR pop ;
                  
          0;
                    
          goto _L7
          _L6:
                  (Number);
                  intValue();
          _L7:
                  
          return;
          _L4:
                  
          return super.hashCode();
              }

              
          final Object CGLIB$clone$6()
                  
          throws CloneNotSupportedException
              {
                  
          return super.clone();
              }

              
          protected final Object clone()
                  
          throws CloneNotSupportedException
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          37;
                     
          goto _L3 _L4
          _L3:
                  
          this;
                  CGLIB$clone$
          6$Method;
                  CGLIB$emptyArgs;
                  CGLIB$clone$
          6$Proxy;
                  intercept();
                  
          return;
          _L4:
                  
          return super.clone();
              }

              
          final boolean CGLIB$equals$7(Object obj)
              {
                  
          return super.equals(obj);
              }

              
          public final boolean equals(Object obj)
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          57;
                     
          goto _L3 _L4
          _L3:
                  
          this;
                  CGLIB$equals$
          7$Method;
                  
          new Object[] {
                      obj
                  };
                  CGLIB$equals$
          7$Proxy;
                  intercept();
                  JVM INSTR dup ;
                  JVM INSTR ifnonnull 
          50;
                     
          goto _L5 _L6
          _L5:
                  JVM INSTR pop ;
                  
          false;
                    
          goto _L7
          _L6:
                  (Boolean);
                  booleanValue();
          _L7:
                  
          return;
          _L4:
                  
          return super.equals(obj);
              }

              
          final String CGLIB$toString$8()
              {
                  
          return super.toString();
              }

              
          public final String toString()
              {
                  CGLIB$CALLBACK_0;
                  
          if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
          _L1:
                  JVM INSTR pop ;
                  CGLIB$BIND_CALLBACKS(
          this);
                  CGLIB$CALLBACK_0;
          _L2:
                  JVM INSTR dup ;
                  JVM INSTR ifnull 
          40;
                     
          goto _L3 _L4
          _L3:
                  
          this;
                  CGLIB$toString$
          8$Method;
                  CGLIB$emptyArgs;
                  CGLIB$toString$
          8$Proxy;
                  intercept();
                  (String);
                  
          return;
          _L4:
                  
          return super.toString();
              }

              
          public static MethodProxy CGLIB$findMethodProxy(Signature signature)
              {
                  String s 
          = signature.toString();
                  s;
                  s.hashCode();
                  JVM INSTR lookupswitch 
          9default 200
              
          //                   -1949253108: 92
              
          //                   -1574182249: 104
              
          //                   -1166709331: 116
              
          //                   -508378822: 128
              
          //                   -358764054: 140
              
          //                   598313209: 152
              
          //                   1826985398: 164
              
          //                   1913648695: 176
              
          //                   1984935277: 188;
                     goto _L1 _L2 _L3 _L4 _L5 _L6 _L7 _L8 _L9 _L10
          _L2:
                  
          "update()V";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L11 _L12
          _L12:
                  
          break MISSING_BLOCK_LABEL_201;
          _L11:
                  
          return CGLIB$update$3$Proxy;
          _L3:
                  
          "finalize()V";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L13 _L14
          _L14:
                  
          break MISSING_BLOCK_LABEL_201;
          _L13:
                  
          return CGLIB$finalize$4$Proxy;
          _L4:
                  
          "query()V";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L15 _L16
          _L16:
                  
          break MISSING_BLOCK_LABEL_201;
          _L15:
                  
          return CGLIB$query$2$Proxy;
          _L5:
                  
          "clone()Ljava/lang/Object;";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L17 _L18
          _L18:
                  
          break MISSING_BLOCK_LABEL_201;
          _L17:
                  
          return CGLIB$clone$6$Proxy;
          _L6:
                  
          "delete()V";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L19 _L20
          _L20:
                  
          break MISSING_BLOCK_LABEL_201;
          _L19:
                  
          return CGLIB$delete$0$Proxy;
          _L7:
                  
          "create()V";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L21 _L22
          _L22:
                  
          break MISSING_BLOCK_LABEL_201;
          _L21:
                  
          return CGLIB$create$1$Proxy;
          _L8:
                  
          "equals(Ljava/lang/Object;)Z";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L23 _L24
          _L24:
                  
          break MISSING_BLOCK_LABEL_201;
          _L23:
                  
          return CGLIB$equals$7$Proxy;
          _L9:
                  
          "toString()Ljava/lang/String;";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L25 _L26
          _L26:
                  
          break MISSING_BLOCK_LABEL_201;
          _L25:
                  
          return CGLIB$toString$8$Proxy;
          _L10:
                  
          "hashCode()I";
                  equals();
                  JVM INSTR ifeq 
          201;
                     
          goto _L27 _L28
          _L28:
                  
          break MISSING_BLOCK_LABEL_201;
          _L27:
                  
          return CGLIB$hashCode$5$Proxy;
          _L1:
                  JVM INSTR pop ;
                  
          return null;
              }

              
          public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[])
              {
                  CGLIB$THREAD_CALLBACKS.set(acallback);
              }

              
          public static void CGLIB$SET_STATIC_CALLBACKS(Callback acallback[])
              {
                  CGLIB$STATIC_CALLBACKS 
          = acallback;
              }

              
          private static final void CGLIB$BIND_CALLBACKS(Object obj)
              {
                  CGLIB.STATIC_CALLBACKS static_callbacks 
          = (CGLIB.STATIC_CALLBACKS)obj;
                  
          if(static_callbacks.CGLIB$BOUND) goto _L2; else goto _L1
          _L1:
                  Object obj1;
                  static_callbacks.CGLIB$BOUND 
          = true;
                  obj1 
          = CGLIB$THREAD_CALLBACKS.get();
                  obj1;
                  
          if(obj1 != nullgoto _L4; else goto _L3
          _L3:
                  JVM INSTR pop ;
                  CGLIB$STATIC_CALLBACKS;
                  
          if(CGLIB$STATIC_CALLBACKS != nullgoto _L4; else goto _L5
          _L5:
                  JVM INSTR pop ;
                    
          goto _L2
          _L4:
                  (Callback[]);
                  static_callbacks;
                  JVM INSTR swap ;
                  
          0;
                  JVM INSTR aaload ;
                  (MethodInterceptor);
                  CGLIB$CALLBACK_0;
          _L2:
              }

              
          public Object newInstance(Callback acallback[])
              {
                  CGLIB$SET_THREAD_CALLBACKS(acallback);
                  CGLIB$SET_THREAD_CALLBACKS(
          null);
                  
          return new <init>();
              }

              
          public Object newInstance(Callback callback)
              {
                  CGLIB$SET_THREAD_CALLBACKS(
          new Callback[] {
                      callback
                  });
                  CGLIB$SET_THREAD_CALLBACKS(
          null);
                  
          return new <init>();
              }

              
          public Object newInstance(Class aclass[], Object aobj[], Callback acallback[])
              {
                  CGLIB$SET_THREAD_CALLBACKS(acallback);
                  JVM INSTR 
          new #2   <Class InfoManager$$EnhancerByCGLIB$$de624598>;
                  JVM INSTR dup ;
                  aclass;
                  aclass.length;
                  JVM INSTR tableswitch 
          0 0default 35
              
          //                   0 28;
                     goto _L1 _L2
          _L2:
                  JVM INSTR pop ;
                  
          <init>();
                    
          goto _L3
          _L1:
                  JVM INSTR pop ;
                  
          throw new IllegalArgumentException("Constructor not found");
          _L3:
                  CGLIB$SET_THREAD_CALLBACKS(
          null);
                  
          return;
              }

              
          public Callback getCallback(int i)
              {
                  CGLIB$BIND_CALLBACKS(
          this);
                  
          this;
                  i;
                  JVM INSTR tableswitch 
          0 0default 30
              
          //                   0 24;
                     goto _L1 _L2
          _L2:
                  CGLIB$CALLBACK_0;
                    
          goto _L3
          _L1:
                  JVM INSTR pop ;
                  
          null;
          _L3:
                  
          return;
              }

              
          public void setCallback(int i, Callback callback)
              {
                  
          this;
                  callback;
                  i;
                  JVM INSTR tableswitch 
          0 0default 29
              
          //                   0 20;
                     goto _L1 _L2
          _L2:
                  (MethodInterceptor);
                  CGLIB$CALLBACK_0;
                    
          goto _L3
          _L1:
                  JVM INSTR pop2 ;
          _L3:
              }

              
          public Callback[] getCallbacks()
              {
                  CGLIB$BIND_CALLBACKS(
          this);
                  
          this;
                  
          return (new Callback[] {
                      CGLIB$CALLBACK_0
                  });
              }

              
          public void setCallbacks(Callback acallback[])
              {
                  
          this;
                  acallback;
                  JVM INSTR dup2 ;
                  
          0;
                  JVM INSTR aaload ;
                  (MethodInterceptor);
                  CGLIB$CALLBACK_0;
              }

              
          private boolean CGLIB$BOUND;
              
          private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
              
          private static final Callback CGLIB$STATIC_CALLBACKS[];
              
          private MethodInterceptor CGLIB$CALLBACK_0;
              
          private static final Method CGLIB$delete$0$Method;
              
          private static final MethodProxy CGLIB$delete$0$Proxy;
              
          private static final Object CGLIB$emptyArgs[];
              
          private static final Method CGLIB$create$1$Method;
              
          private static final MethodProxy CGLIB$create$1$Proxy;
              
          private static final Method CGLIB$query$2$Method;
              
          private static final MethodProxy CGLIB$query$2$Proxy;
              
          private static final Method CGLIB$update$3$Method;
              
          private static final MethodProxy CGLIB$update$3$Proxy;
              
          private static final Method CGLIB$finalize$4$Method;
              
          private static final MethodProxy CGLIB$finalize$4$Proxy;
              
          private static final Method CGLIB$hashCode$5$Method;
              
          private static final MethodProxy CGLIB$hashCode$5$Proxy;
              
          private static final Method CGLIB$clone$6$Method;
              
          private static final MethodProxy CGLIB$clone$6$Proxy;
              
          private static final Method CGLIB$equals$7$Method;
              
          private static final MethodProxy CGLIB$equals$7$Proxy;
              
          private static final Method CGLIB$toString$8$Method;
              
          private static final MethodProxy CGLIB$toString$8$Proxy;

              
          static 
              {
                  CGLIB$STATICHOOK1();
              }

              
          public ()
              {
                  CGLIB$BIND_CALLBACKS(
          this);
              }
          }


          附件如下:
          cglib sample

          posted on 2008-03-16 22:50 stone2083 閱讀(35634) 評論(22)  編輯  收藏 所屬分類: java

          Feedback

          # re: CGlib簡單介紹 2008-07-03 16:51 zhen

          用cglib也產生了附加的問題  回復  更多評論   

          # re: CGlib簡單介紹 2008-07-03 22:07 stone2083

          不可否認,每項技術總會存在弊端,比如cglib,導致jvm Permanet Generation 不再穩(wěn)定,如果配置不當,并且大量生成cglib代理類的時候,出現(xiàn)out of memory;
          又或者,調試代理類的時候,相當不方便...
          但是cglib有他可喜的一面,底層采用asm,動態(tài)生成字節(jié)碼,比jdk proxy效率高了不知多少;為spring aop提供了底層的一種實現(xiàn);hibernate使用cglib動態(tài)生成DO/PO (接口層對象)字節(jié)碼...應用是何等的廣泛.
          為java靜態(tài)語言提供了動態(tài)特性(當然,底層是asm功勞),多么可喜.

          我不清楚,你所謂使用cglib產生附加問題,具體是什么問題?  回復  更多評論   

          # re: CGlib簡單介紹 2008-10-03 21:34 大鵬

          太強了,我頂!  回復  更多評論   

          # re: CGlib簡單介紹 2009-05-05 16:16 SunnyWolf

          NB  回復  更多評論   

          # re: CGlib簡單介紹 2009-09-16 11:04 tomcatlee

          牛掰的東東啊  回復  更多評論   

          # re: CGlib簡單介紹 2009-10-09 16:40 名揚/六耶子

          可以通過cglib動態(tài)創(chuàng)建java對象么?就是傳入對象名,字段名,然后創(chuàng)建并返回所創(chuàng)建對象的實例?  回復  更多評論   

          # re: CGlib簡單介紹 2009-10-10 10:38 stone2083

          @名揚/六耶子
          cglib底層依賴了asm,它主要是在“動態(tài)代理”場景下增加易用性。
          如果要動態(tài)生成字段,方法,那么asm或者javassist這兩個技術,更合適你。  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2010-04-08 16:49 tylerLimin

          不錯!  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2010-09-28 22:46 pyzhu

          "有興趣的朋友可以看看我反編譯的InfoManager的子類,就可以很明白知道具體的實現(xiàn)了。"
          這個cglib在運行期動態(tài)生成的class你是如何獲取的,并用jad進行反編碼的?
          一直沒找到這個動態(tài)生成的class我也就無法對它進行反編譯,莫非是直接放在jvm的堆內存了吧?那該如何獲取它并反編譯它呢。。。
          期待答復~  回復  更多評論   

          # re: CGlib簡單介紹 2010-09-29 09:18 stone2083

          @pyzhu
          用了比較猥瑣的辦法,
          debug,將動態(tài)生成class的字節(jié)碼 輸入到文件中,然后反編譯得到的.  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2010-09-29 23:11 pyzhu

          @stone2083
          一語驚醒夢中人,呵呵。。。
          可是還有些不明白的地方,如何通過Class對象獲取對應class字節(jié)碼呀?  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2010-09-29 23:22 pyzhu

          @stone2083
          呵呵。。。想到一種方式,用javassist的ClassPool/CtClass應該可以做到~  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2010-10-06 01:36 pyzhu

          我發(fā)現(xiàn)我真是傻呀,竟然一直去尋找這樣一種方式:“如何通過Class實例對象得到class字節(jié)碼,然后將字節(jié)碼寫入文件再反編譯,如此來獲取源碼”。。。
          哈哈。。。真是笨得要命哦~
          反倒忘記了cglib的source code了,嘻嘻。。。直接修改net.sf.cglib.core.AbstractClassGenerator.create(Object key)方法,將cglib取到的字節(jié)碼寫入文檔再反編譯不就ok了么~

          ps. javassist貌似不行  回復  更多評論   

          # re: CGlib簡單介紹 2010-10-09 09:27 stone2083

          @pyzhu
          修改源碼也是一種方法 :)
          我是在debug的時候,Variables窗體中,編寫java代碼,拿到class變量信息做自己的處理


            回復  更多評論   

          # re: CGlib簡單介紹 2010-11-03 13:31 stone2083

          @pyzhu
          得到同事指點,還有一種更好的方法:
          system.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定輸出目錄"); 

          詳見:http://www.javaeye.com/topic/799827  回復  更多評論   

          # re: CGlib簡單介紹 2011-11-09 15:21 yaohonv

          學習  回復  更多評論   

          # re: CGlib簡單介紹 2013-10-24 16:14 擠饅頭

          樓主的代碼有無限遞歸啊。。。  回復  更多評論   

          # re: CGlib簡單介紹 2013-10-24 16:18 擠饅頭

          @擠饅頭
          看錯了,沒問題  回復  更多評論   

          # re: CGlib簡單介紹 2013-11-06 22:26 diegozhu

          @stone2083

          1. PG 不再穩(wěn)定.
          2. debug困難.  回復  更多評論   

          # re: CGlib簡單介紹 2014-01-24 10:28 frogSF

          反編譯那段太難懂了~~~~
            回復  更多評論   

          # re: CGlib簡單介紹 2014-08-02 11:50 wanglj

          受教了,謝謝!將代碼download下來后,跑了跑,比之前的理解清晰多了。  回復  更多評論   

          # re: CGlib簡單介紹[未登錄] 2015-10-05 11:41 jones

          怎么反編譯子類?  回復  更多評論   

          主站蜘蛛池模板: 望城县| 福州市| 咸阳市| 莲花县| 成武县| 榆林市| 锡林浩特市| 大埔区| 廊坊市| 新乡县| 宁陵县| 潮州市| 宜川县| 白水县| 南郑县| 平武县| 阳东县| 南丹县| 沂源县| 依安县| 右玉县| 和静县| 镇雄县| 彭州市| 齐齐哈尔市| 湖南省| 凉城县| 高台县| 汕头市| 车致| 三门峡市| 城市| 南昌市| 洛扎县| 锦州市| 光山县| 铜梁县| 墨脱县| 秦安县| 巴林左旗| 奉化市|