美文网首页
cglib学习笔记

cglib学习笔记

作者: realqiyan | 来源:发表于2017-04-24 00:17 被阅读0次

    cglib学习笔记

    cglib简介

    cglib:Code Generation Library
    主页:https://github.com/cglib/cglib/
    教程:https://github.com/cglib/cglib/wiki/Tutorial

    cglib是java字节码生成和转换类库。它用于AOP,测试,数据访问框架,生成动态代理对象和拦截字段访问。
    cglib基于ASM,通过ASM生成新的字节码。

    cglib网络图片

    cglib学习

    Enhancer

    字节码增强功能,主要用于生成新的class,spring的aop就会使用cglib生成代理类。

    通过设置Enhancer属性,然后通过Enhancer#create生成新的增强类。

    通过设置cglib.debugLocation可以指定生成class dump存放路径,通过查看生成的class更方便学习。

    System.setProperty("cglib.debugLocation", "/Users/qiyan/cglib/classes");
    

    首先来一个简单的POJO做为例子:

    public class SampleClass {
      public String test(String input) {
        return "Hello world!";
      }
    }
    

    Enhancer使用说明:

    Enhancer enhancer = new Enhancer();
    //设置Enhancer属性
    enhancer.create();//创建增强类
    

    Enhancer属性说明:

    //增强类集成的接口列表
    Class[] interfaces;
    
    //父类
    Class superclass;
    
    //Callback选择器 返回值为callbacks的下标
    CallbackFilter filter;
    
    //回调处理器MethodInterceptor|NoOp|LazyLoader|Dispatcher|InvocationHandler|FixedValue的实现类
    Callback[] callbacks;
    
    //回调处理器类型MethodInterceptor|NoOp|LazyLoader|Dispatcher|InvocationHandler|FixedValue的Class
    Type[] callbackTypes;
    
    //是否使用工厂类
    boolean useFactory = true;
    
    //是否允许调用代理类构造器
    boolean interceptDuringConstruction = true;
    
    //是否校验回调类型
    boolean validateCallbackTypes;
    
    //是否仅创建代理类
    boolean classOnly;
    
    //是否仅创建工厂类
    boolean factoryOnly;
    
    //参数类型
    Class[] argumentTypes;
    
    //参数
    Object[] arguments;
    

    FixedValue

    使用Enhancer生成代理类,callback设置为FixedValue
    使用FixedValue以后,所有接口都会返回固定值,test,toString,hashCode都会返回固定值,但是hashCode会因为数据转换抛出异常。

    public static void testFixedValue() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        enhancer.setCallback(new FixedValue() {
            @Override
            public Object loadObject() throws Exception {
                return "Hello cglib!";
            }
        });
        SampleClass proxy = (SampleClass) enhancer.create();
        System.out.println(proxy.test("1"));//输出结果Hello cglib!
        System.out.println(proxy.toString());//输出结果Hello cglib!
        System.out.println(proxy.hashCode());//异常(类型转换异常)
    }
    

    cglib会生成两个class,一个工厂类,一个代理类:

    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.Factory;
    import net.sf.cglib.proxy.FixedValue;
    
    public class SampleClass$$EnhancerByCGLIB$$9bebc1cf
      implements Factory
    {
      private boolean CGLIB$BOUND;
      public static Object CGLIB$FACTORY_DATA;
      private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
      private static final Callback[] CGLIB$STATIC_CALLBACKS;
      private FixedValue CGLIB$CALLBACK_0;
      
      public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
      }
      
      public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
      }
      
      private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
      {
        9bebc1cf local9bebc1cf = (9bebc1cf)paramObject;
        if (!local9bebc1cf.CGLIB$BOUND)
        {
          local9bebc1cf.CGLIB$BOUND = true;
          Object tmp23_20 = CGLIB$THREAD_CALLBACKS.get();
          if (tmp23_20 == null)
          {
            tmp23_20;
            CGLIB$STATIC_CALLBACKS;
          }
          local9bebc1cf.CGLIB$CALLBACK_0 = (tmp31_28 == null ? tmp31_28 : (FixedValue)((Callback[])tmp23_20)[0]);
        }
      }
      
      public Object newInstance(Callback[] paramArrayOfCallback)
      {
        SampleClass..EnhancerByCGLIB..354348a.CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
        SampleClass..EnhancerByCGLIB..354348a.CGLIB$SET_THREAD_CALLBACKS(null);
        return new SampleClass..EnhancerByCGLIB..354348a();
      }
      
      public Object newInstance(Callback paramCallback)
      {
        SampleClass..EnhancerByCGLIB..354348a.CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
        SampleClass..EnhancerByCGLIB..354348a.CGLIB$SET_THREAD_CALLBACKS(null);
        return new SampleClass..EnhancerByCGLIB..354348a();
      }
      
      /* Error */
      public Object newInstance(Class[] arg1, Object[] arg2, Callback[] arg3)
      {
        // Byte code:
        //   0: aload_3
        //   1: invokestatic 52 cglib/SampleClass$$EnhancerByCGLIB$$354348a:CGLIB$SET_THREAD_CALLBACKS  ([Lnet/sf/cglib/proxy/Callback;)V
        //   4: new 50  cglib/SampleClass$$EnhancerByCGLIB$$354348a
        //   7: dup
        //   8: aload_1
        //   9: dup
        //   10: arraylength
        //   11: tableswitch    default:+24->35, 0:+17->28
        //   28: pop
        //   29: invokespecial 53   cglib/SampleClass$$EnhancerByCGLIB$$354348a:<init>  ()V
        //   32: goto +17 -> 49
        //   35: goto +3 -> 38
        //   38: pop
        //   39: new 59 java/lang/IllegalArgumentException
        //   42: dup
        //   43: ldc 61
        //   45: invokespecial 64   java/lang/IllegalArgumentException:<init>   (Ljava/lang/String;)V
        //   48: athrow
        //   49: aconst_null
        //   50: invokestatic 52    cglib/SampleClass$$EnhancerByCGLIB$$354348a:CGLIB$SET_THREAD_CALLBACKS  ([Lnet/sf/cglib/proxy/Callback;)V
        //   53: areturn
      }
      
      public Callback getCallback(int paramInt)
      {
        CGLIB$BIND_CALLBACKS(this);
        switch (paramInt)
        {
        case 0: 
          break;
        }
        return null;
      }
      
      public void setCallback(int paramInt, Callback paramCallback)
      {
        switch (paramInt)
        {
        case 0: 
          this.CGLIB$CALLBACK_0 = ((FixedValue)paramCallback);
          break;
        }
      }
      
      public Callback[] getCallbacks()
      {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[] { this.CGLIB$CALLBACK_0 };
      }
      
      public void setCallbacks(Callback[] paramArrayOfCallback)
      {
        this.CGLIB$CALLBACK_0 = ((FixedValue)paramArrayOfCallback[0]);
      }
    }
    

    cglib生成的代理类:

    import net.sf.cglib.proxy.Callback;
    import net.sf.cglib.proxy.Factory;
    import net.sf.cglib.proxy.FixedValue;
    
    public class SampleClass$$EnhancerByCGLIB$$354348a
      extends SampleClass
      implements Factory
    {
      private boolean CGLIB$BOUND;
      public static Object CGLIB$FACTORY_DATA;
      private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
      private static final Callback[] CGLIB$STATIC_CALLBACKS;
      private FixedValue CGLIB$CALLBACK_0;
      
      /* Error */
      static void CGLIB$STATICHOOK1()
      {
        // Byte code:
        //   0: new 21  java/lang/ThreadLocal
        //   3: dup
        //   4: invokespecial 24    java/lang/ThreadLocal:<init>    ()V
        //   7: putstatic 26    cglib/SampleClass$$EnhancerByCGLIB$$354348a:CGLIB$THREAD_CALLBACKS  Ljava/lang/ThreadLocal;
        //   10: return
        //   11: athrow
      }
      
      public final String test(String paramString)
      {
        FixedValue tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        return (String)this.CGLIB$CALLBACK_0.loadObject();
      }
      
      public final boolean equals(Object paramObject)
      {
        FixedValue tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        Object tmp22_17 = this.CGLIB$CALLBACK_0.loadObject();
        tmp22_17;
        return tmp22_17 == null ? false : ((Boolean)tmp22_17).booleanValue();
      }
      
      public final String toString()
      {
        FixedValue tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        return (String)this.CGLIB$CALLBACK_0.loadObject();
      }
      
      public final int hashCode()
      {
        FixedValue tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        Object tmp22_17 = this.CGLIB$CALLBACK_0.loadObject();
        tmp22_17;
        return tmp22_17 == null ? 0 : ((Number)tmp22_17).intValue();
      }
      
      protected final Object clone()
        throws CloneNotSupportedException
      {
        FixedValue tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        return this.CGLIB$CALLBACK_0.loadObject();
      }
      
      public SampleClass$$EnhancerByCGLIB$$354348a()
      {
        CGLIB$BIND_CALLBACKS(this);
      }
      
      public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$THREAD_CALLBACKS.set(paramArrayOfCallback);
      }
      
      public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] paramArrayOfCallback)
      {
        CGLIB$STATIC_CALLBACKS = paramArrayOfCallback;
      }
      
      private static final void CGLIB$BIND_CALLBACKS(Object paramObject)
      {
        354348a local354348a = (354348a)paramObject;
        if (!local354348a.CGLIB$BOUND)
        {
          local354348a.CGLIB$BOUND = true;
          Object tmp23_20 = CGLIB$THREAD_CALLBACKS.get();
          if (tmp23_20 == null)
          {
            tmp23_20;
            CGLIB$STATIC_CALLBACKS;
          }
          local354348a.CGLIB$CALLBACK_0 = (tmp31_28 == null ? tmp31_28 : (FixedValue)((Callback[])tmp23_20)[0]);
        }
      }
      
      public Object newInstance(Callback[] paramArrayOfCallback)
      {
        CGLIB$SET_THREAD_CALLBACKS(paramArrayOfCallback);
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new 354348a();
      }
      
      public Object newInstance(Callback paramCallback)
      {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[] { paramCallback });
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new 354348a();
      }
      
      /* Error */
      public Object newInstance(Class[] arg1, Object[] arg2, Callback[] arg3)
      {
        // Byte code:
        //   0: aload_3
        //   1: invokestatic 83 cglib/SampleClass$$EnhancerByCGLIB$$354348a:CGLIB$SET_THREAD_CALLBACKS  ([Lnet/sf/cglib/proxy/Callback;)V
        //   4: new 2   cglib/SampleClass$$EnhancerByCGLIB$$354348a
        //   7: dup
        //   8: aload_1
        //   9: dup
        //   10: arraylength
        //   11: tableswitch    default:+24->35, 0:+17->28
        //   28: pop
        //   29: invokespecial 84   cglib/SampleClass$$EnhancerByCGLIB$$354348a:<init>  ()V
        //   32: goto +17 -> 49
        //   35: goto +3 -> 38
        //   38: pop
        //   39: new 90 java/lang/IllegalArgumentException
        //   42: dup
        //   43: ldc 92
        //   45: invokespecial 95   java/lang/IllegalArgumentException:<init>   (Ljava/lang/String;)V
        //   48: athrow
        //   49: aconst_null
        //   50: invokestatic 83    cglib/SampleClass$$EnhancerByCGLIB$$354348a:CGLIB$SET_THREAD_CALLBACKS  ([Lnet/sf/cglib/proxy/Callback;)V
        //   53: areturn
      }
      
      public Callback getCallback(int paramInt)
      {
        CGLIB$BIND_CALLBACKS(this);
        switch (paramInt)
        {
        case 0: 
          break;
        }
        return null;
      }
      
      public void setCallback(int paramInt, Callback paramCallback)
      {
        switch (paramInt)
        {
        case 0: 
          this.CGLIB$CALLBACK_0 = ((FixedValue)paramCallback);
          break;
        }
      }
      
      public Callback[] getCallbacks()
      {
        CGLIB$BIND_CALLBACKS(this);
        return new Callback[] { this.CGLIB$CALLBACK_0 };
      }
      
      public void setCallbacks(Callback[] paramArrayOfCallback)
      {
        this.CGLIB$CALLBACK_0 = ((FixedValue)paramArrayOfCallback[0]);
      }
      
      static {}
    }
    

    MethodInterceptor

    高级一点的回调方法:

    public static void testMethodInterceptor() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
                    throws Throwable {
                if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
                    return "Hello cglib!";
                } else {
                    return proxy.invokeSuper(obj, args);
                }
            }
        });
        SampleClass proxy = (SampleClass) enhancer.create();
        System.out.println(proxy.test("1"));//输出结果Hello cglib!
        System.out.println(proxy.toString());//输出结果cglib.SampleClass$$EnhancerByCGLIB$$e7ad6a0f@53e25b76
        System.out.println(proxy.hashCode());//输出结果1407343478
    }
    
    

    生成的代理方法:

     public final String test(String paramString)
      {
        MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
        if (tmp4_1 == null)
        {
          tmp4_1;
          CGLIB$BIND_CALLBACKS(this);
        }
        MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
        if (tmp17_14 != null) {
          return (String)tmp17_14.intercept(this, CGLIB$test$0$Method, new Object[] { paramString }, CGLIB$test$0$Proxy);
        }
        return super.test(paramString);
      }
    

    InvocationHandler

    public static void testInvocationHandler() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(SampleClass.class);
        enhancer.setCallback(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(method.getReturnType() == String.class) {
                    System.out.print("cglib -> "+method.toGenericString());
                    return "Hello cglib!";
                } else {
                    throw new RuntimeException("Do not know what to do.");
                }
            }
        });
        SampleClass proxy = (SampleClass) enhancer.create();
        System.out.println(proxy.test("1"));//输出结果cglib -> public java.lang.String cglib.SampleClass.test(java.lang.String)Hello cglib!
        System.out.println(proxy.toString());//cglib -> public java.lang.String java.lang.Object.toString()Hello cglib!
        System.out.println(proxy.hashCode());//异常(java.lang.RuntimeException: Do not know what to do.)
    }
    

    NoOp|LazyLoader|Dispatcher

    NoOp|LazyLoader|Dispatcher就不重复了,生成的类细节可以自行去class dump的目录查看。

    Immutable bean

    生成不可变对象,可以用于参数传递时防止对象参数修改的场景。

    原始对象是可以继续修改的,并且修改的值会影响不可变的对象。

    例子:

    public class SampleBean {
      private String value;
      public String getValue() {
        return value;
      }
      public void setValue(String value) {
        this.value = value;
      }
    }
    

    测试方法:

     public static void testImmutableBean() throws Exception {
        SampleBean bean = new SampleBean();
        bean.setValue("Hello world!");
        SampleBean immutableBean = (SampleBean) ImmutableBean.create(bean);
        System.out.println(immutableBean.getValue());//Hello world!
        bean.setValue("Hello world, again!");
        System.out.println(immutableBean.getValue());//Hello world, again!
        immutableBean.setValue("Hello cglib!"); // 抛出异常
    }
    

    cglib生成的不可变对象:

    public class SampleBean$$ImmutableBeanByCGLIB$$b26aa907
      extends SampleBean
    {
      private final SampleBean CGLIB$RWBean;
      
      public SampleBean$$ImmutableBeanByCGLIB$$b26aa907(Object paramObject)
      {
        this.CGLIB$RWBean = ((SampleBean)paramObject);
      }
      
      public String getValue()
      {
        return this.CGLIB$RWBean.getValue();
      }
      
      public void setValue(String paramString)
      {
        throw new IllegalStateException("Bean is immutable");
      }
    }
    

    Bean generator

    用于运行时动态生成class。

    例子:

    public static void testBeanGenerator() throws Exception {
        BeanGenerator beanGenerator = new BeanGenerator();
        beanGenerator.addProperty("value", String.class);
        Object myBean = beanGenerator.create();
        Method setter = myBean.getClass().getMethod("setValue", String.class);
        setter.invoke(myBean, "Hello cglib!");
        Method getter = myBean.getClass().getMethod("getValue");
        System.out.println(getter.invoke(myBean));
    }
    

    cglib生成的class:

    package net.sf.cglib.empty;
    
    public class Object$$BeanGeneratorByCGLIB$$60b0c82c
    {
      private String $cglib_prop_value;
      
      public String getValue()
      {
        return this.$cglib_prop_value;
      }
      
      public void setValue(String paramString)
      {
        this.$cglib_prop_value = paramString;
      }
    }
    
    

    Bean copier

    Bulk bean

    Bean map

    Key factory

    Mixin

    String switcher

    Interface maker

    Method delegate

    Multicast delegate

    Constructor delegate

    Parallel sorter

    Fast class and fast members

    相关文章

      网友评论

          本文标题:cglib学习笔记

          本文链接:https://www.haomeiwen.com/subject/kiruzttx.html