`

jdk cglib 动态代理

阅读更多

1 jdk动态代理

  jdk动态代理限制:只能对实现了某一个接口的类进行代理。

  原理:生成的代理类也实现了被代理类实现的接口,并且继承了Proxy类

  jdk提供动态代理的工具:接口:java.lang.reflect.InvocationHandler, java.lang.reflect.Proxy;

 

  实现jdk动态代理步骤:

  首先定义被代理的类及被代理类实现的接口:

 

interface Movable {
	public void move();
}

class Car implements Movable {
	public void move () {
		System.out.println("car is moving...");
	}
}

  

 

   定义自己的InvocationHandler

  

abstract class CarInvocationHandler implements InvocationHandler {

	private Movable movable;
	
	CarInvocationHandler(Movable movable) {
		this.movable = movable;
	}
	
	public Movable getProxyInstance() {
		return (Movable)Proxy.newProxyInstance(Movable.class.getClassLoader(), new Class[]{Movable.class}, this);
	}
	
        public Class getProxyClass() {
		return Proxy.getProxyClass(Movable.class.getClassLoader(), new Class[]{});
	}
	@Override
	public abstract Object invoke(Object proxy, Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
	
	public Movable getMovalbe() {
		return this.movable;
	}
	
}

class CarTimeInvocationHandler extends CarInvocationHandler {

	CarTimeInvocationHandler(Movable movable) {
		super(movable);
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		System.out.println("startTime: " + System.currentTimeMillis());
		Object result = method.invoke(this.getMovalbe(), args);
		System.out.println("end: " + System.currentTimeMillis());
		return result;
	}
	
}

   实现InvocationHandler时,进行了少量封装,方便实现多种代理的InvocationHandler

 

 

   获取代理类:调用invocationHanlder的getProxyInstance()方法;想要获取代理类的类可以调用getProxyClass()方法

 

   jdk动态代理原理:

     


 Proxy.newProxyInstance()源码为

 

public static Object newProxyInstance(ClassLoader loader,
					  Class<?>[] interfaces,
					  InvocationHandler h)
	throws IllegalArgumentException
    {
	if (h == null) {
	    throw new NullPointerException();
	}

	/*
	 * Look up or generate the designated proxy class.
	 */
	Class cl = getProxyClass(loader, interfaces);

	/*
	 * Invoke its constructor with the designated invocation handler.
	 */
	try {
	    Constructor cons = cl.getConstructor(constructorParams);
	    return (Object) cons.newInstance(new Object[] { h });
	} catch (NoSuchMethodException e) {
	    throw new InternalError(e.toString());
	} catch (IllegalAccessException e) {
	    throw new InternalError(e.toString());
	} catch (InstantiationException e) {
	    throw new InternalError(e.toString());
	} catch (InvocationTargetException e) {
	    throw new InternalError(e.toString());
	}
    }

    由上图源码可知:Proxy首先获取到被代理类的class:Class cl = getProxyClass(loader, interfaces); 然后根据Class得到代理类的构造函数,然后根据构造函数生成代理类示例,也就是使用了反射。

 

   那么Proxy怎么获取代理类的Class呢?下面是Proxy getProxyClass主要源码:

  

    private byte[] generateClassFile() {

	/* ============================================================
	 * Step 1: Assemble ProxyMethod objects for all methods to
	 * generate proxy dispatching code for.
	 */

	/*
	 * Record that proxy methods are needed for the hashCode, equals,
	 * and toString methods of java.lang.Object.  This is done before
	 * the methods from the proxy interfaces so that the methods from
	 * java.lang.Object take precedence over duplicate methods in the
	 * proxy interfaces.
	 */
	addProxyMethod(hashCodeMethod, Object.class);
	addProxyMethod(equalsMethod, Object.class);
	addProxyMethod(toStringMethod, Object.class);

	/*
	 * Now record all of the methods from the proxy interfaces, giving
	 * earlier interfaces precedence over later ones with duplicate
	 * methods.
	 */
	for (int i = 0; i < interfaces.length; i++) {
	    Method[] methods = interfaces[i].getMethods();
	    for (int j = 0; j < methods.length; j++) {
		addProxyMethod(methods[j], interfaces[i]);
	    }
	}

	/*
	 * For each set of proxy methods with the same signature,
	 * verify that the methods' return types are compatible.
	 */
	for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
	    checkReturnTypes(sigmethods);
	}

	/* ============================================================
	 * Step 2: Assemble FieldInfo and MethodInfo structs for all of
	 * fields and methods in the class we are generating.
	 */
	try {
	    methods.add(generateConstructor());

	    for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
		for (ProxyMethod pm : sigmethods) {

		    // add static field for method's Method object
		    fields.add(new FieldInfo(pm.methodFieldName,
			"Ljava/lang/reflect/Method;",
			 ACC_PRIVATE | ACC_STATIC));

		    // generate code for proxy method and add it
		    methods.add(pm.generateMethod());
		}
	    }

	    methods.add(generateStaticInitializer());

	} catch (IOException e) {
	    throw new InternalError("unexpected I/O Exception");
	}

	if (methods.size() > 65535) {
	    throw new IllegalArgumentException("method limit exceeded");
	}
	if (fields.size() > 65535) {
	    throw new IllegalArgumentException("field limit exceeded");
	}

	/* ============================================================
	 * Step 3: Write the final class file.
	 */

	/*
	 * Make sure that constant pool indexes are reserved for the
	 * following items before starting to write the final class file.
	 */
	cp.getClass(dotToSlash(className));
	cp.getClass(superclassName);
	for (int i = 0; i < interfaces.length; i++) {
	    cp.getClass(dotToSlash(interfaces[i].getName()));
	}

	/*
	 * Disallow new constant pool additions beyond this point, since
	 * we are about to write the final constant pool table.
	 */
	cp.setReadOnly();

	ByteArrayOutputStream bout = new ByteArrayOutputStream();
	DataOutputStream dout = new DataOutputStream(bout);

	try {
	    /*
	     * Write all the items of the "ClassFile" structure.
	     * See JVMS section 4.1.
	     */
					// u4 magic;
	    dout.writeInt(0xCAFEBABE);
					// u2 minor_version;
	    dout.writeShort(CLASSFILE_MINOR_VERSION);
					// u2 major_version;
	    dout.writeShort(CLASSFILE_MAJOR_VERSION);

	    cp.write(dout);		// (write constant pool)

					// u2 access_flags;
	    dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
					// u2 this_class;
	    dout.writeShort(cp.getClass(dotToSlash(className)));
					// u2 super_class;
	    dout.writeShort(cp.getClass(superclassName));

					// u2 interfaces_count;
	    dout.writeShort(interfaces.length);
					// u2 interfaces[interfaces_count];
	    for (int i = 0; i < interfaces.length; i++) {
		dout.writeShort(cp.getClass(
		    dotToSlash(interfaces[i].getName())));
	    }

					// u2 fields_count;
	    dout.writeShort(fields.size());
					// field_info fields[fields_count];
	    for (FieldInfo f : fields) {
		f.write(dout);
	    }

					// u2 methods_count;
	    dout.writeShort(methods.size());
					// method_info methods[methods_count];
	    for (MethodInfo m : methods) {
		m.write(dout);
	    }

	   				 // u2 attributes_count;
	    dout.writeShort(0);	// (no ClassFile attributes for proxy classes)

	} catch (IOException e) {
	    throw new InternalError("unexpected I/O Exception");
	}

	return bout.toByteArray();
    }

    由上可知:首先生成成员变量,代理方法,然后做一定的检查,然后返回字节码。

  

    以下是生成代理类的代码:

  

import com.malone.proxy.Movable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class Proxy11 extends Proxy
  implements Movable
{
  private static Method m1;
  private static Method m3;
  private static Method m0;
  private static Method m2;

  public Proxy11(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final void move()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m2, null));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.malone.proxy.Movable").getMethod("move", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

   由生成代理类的代码可知,代理类实现了被代理类实现的接口,继承了Proxy类,代理类的构造函数会把参赛handler赋给Proxy类的handler,根据代理类创建代理类对象时,

  

	    Constructor cons = cl.getConstructor(constructorParams);
	    return (Object) cons.newInstance(new Object[] { h });

    Proxy.newInstance()方法中传递的handler传递到代理类的构造函数里,及赋给了Proxy的handler。

   当代理类调用equals,hashCode, toString,和代理类实现接口中的方法时,实际上执行的是自己定义的invocationHanlder的invoke方法。

   jdk生成代理时,我们很难找到代理类的class文件

  利用下面一个工具方法可以指定生成class文件路径:

 

class ProxyGeneratorUtils {  
	  
    /** 
     * 把代理类的字节码写到硬盘上 
     * @param path 保存路径 
     */  
    public static void writeProxyClassToHardDisk(String path) {  
        // 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了  
        // System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);  
          
        // 第二种方法  
          
        // 获取代理类的字节码  
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", Car.class.getInterfaces());  
          
        FileOutputStream out = null;  
          
        try {  
            out = new FileOutputStream(path);  
            out.write(classFile);  
            out.flush();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                out.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}

 

 二 cglib动态代理

      限制:cglib不能代理类的final方法

      原理:cglib通过操作asm,给被代理类生成子类

      和jdk动态代理比较:不需要实现接口

 

  cglib生成动态代理类的主要代码:

 

//被代理类
class TargetClass {
	public void create() {
		System.out.println("create method...");
	}
	
	public void update() {
		System.out.println("update method...");
	}
	
}
   代理实现类

 

class CglibProxy implements MethodInterceptor {

	private Enhancer enhance = new Enhancer();
	
	public Object getProxyInstance(Class<TargetClass> clazz) {
		enhance.setSuperclass(clazz);
		enhance.setCallback(this);
		enhance.setCallbackFilter(new MyCallbackFilter());
		enhance.setCallbacks(new Callback[]{new CglibProxy(), new MyFixedValue()});
		
		return enhance.create();
	}
	
	@Override
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		System.out.println("prefix operate...");
		Object result = proxy.invokeSuper(obj, args);
		System.out.println("after operate...");
		return result;
	}
	
}

 

   生成代理类代码:

// Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov  Date: 2013/10/24 11:19:09
// Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   <generated>

package com.malone.proxy;

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

// Referenced classes of package com.malone.proxy:
//            TargetClass

public class TargetClass$$EnhancerByCGLIB$$a0f953e6 extends TargetClass
    implements Factory
{

    static void CGLIB$STATICHOOK1()
    {
        Class class1;
        ClassLoader classloader;
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        classloader = (class1 = Class.forName("com.malone.proxy.TargetClass$$EnhancerByCGLIB$$a0f953e6")).getClassLoader();
        classloader;
        CGLIB$emptyArgs = new Object[0];
        CGLIB$create$0$Proxy = MethodProxy.create(classloader, (CGLIB$create$0$Method = Class.forName("com.malone.proxy.TargetClass").getDeclaredMethod("create", new Class[0])).getDeclaringClass(), class1, "()V", "create", "CGLIB$create$0");
        CGLIB$update$1$Proxy = MethodProxy.create(classloader, (CGLIB$update$1$Method = Class.forName("com.malone.proxy.TargetClass").getDeclaredMethod("update", new Class[0])).getDeclaringClass(), class1, "()V", "update", "CGLIB$update$1");
        CGLIB$finalize$2$Proxy = MethodProxy.create(classloader, (CGLIB$finalize$2$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize", new Class[0])).getDeclaringClass(), class1, "()V", "finalize", "CGLIB$finalize$2");
        CGLIB$hashCode$3$Proxy = MethodProxy.create(classloader, (CGLIB$hashCode$3$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode", new Class[0])).getDeclaringClass(), class1, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Proxy = MethodProxy.create(classloader, (CGLIB$clone$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone", new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        CGLIB$equals$5$Proxy = MethodProxy.create(classloader, (CGLIB$equals$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals", new Class[] {
            Class.forName("java.lang.Object")
        })).getDeclaringClass(), class1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$5");
        CGLIB$toString$6$Proxy = MethodProxy.create(classloader, (CGLIB$toString$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString", new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/String;", "toString", "CGLIB$toString$6");
        return;
    }

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

    public final void create()
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$0$Method;
        CGLIB$emptyArgs;
        CGLIB$create$0$Proxy;
        intercept();
        return;
        super.create();
        return;
    }

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

    public final void update()
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$1$Method;
        CGLIB$emptyArgs;
        CGLIB$update$1$Proxy;
        intercept();
        return;
        super.update();
        return;
    }

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

    protected final void finalize()
        throws Throwable
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$2$Method;
        CGLIB$emptyArgs;
        CGLIB$finalize$2$Proxy;
        intercept();
        return;
        super.finalize();
        return;
    }

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

    public final int hashCode()
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$3$Method;
        CGLIB$emptyArgs;
        CGLIB$hashCode$3$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$4()
        throws CloneNotSupportedException
    {
        return super.clone();
    }

    protected final Object clone()
        throws CloneNotSupportedException
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$4$Method;
        CGLIB$emptyArgs;
        CGLIB$clone$4$Proxy;
        intercept();
        return;
_L4:
        return super.clone();
    }

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

    public final boolean equals(Object obj)
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$5$Method;
        new Object[] {
            obj
        };
        CGLIB$equals$5$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$6()
    {
        return super.toString();
    }

    public final String toString()
    {
        CGLIB$CALLBACK_0;
        if(CGLIB$CALLBACK_0 != null) goto _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$6$Method;
        CGLIB$emptyArgs;
        CGLIB$toString$6$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 7: default 160
    //                   -1949253108: 76
    //                   -1574182249: 88
    //                   -508378822: 100
    //                   598313209: 112
    //                   1826985398: 124
    //                   1913648695: 136
    //                   1984935277: 148;
           goto _L1 _L2 _L3 _L4 _L5 _L6 _L7 _L8
_L2:
        "update()V";
        equals();
        JVM INSTR ifeq 161;
           goto _L9 _L10
_L10:
        break MISSING_BLOCK_LABEL_161;
_L9:
        return CGLIB$update$1$Proxy;
_L3:
        "finalize()V";
        equals();
        JVM INSTR ifeq 161;
           goto _L11 _L12
_L12:
        break MISSING_BLOCK_LABEL_161;
_L11:
        return CGLIB$finalize$2$Proxy;
_L4:
        "clone()Ljava/lang/Object;";
        equals();
        JVM INSTR ifeq 161;
           goto _L13 _L14
_L14:
        break MISSING_BLOCK_LABEL_161;
_L13:
        return CGLIB$clone$4$Proxy;
_L5:
        "create()V";
        equals();
        JVM INSTR ifeq 161;
           goto _L15 _L16
_L16:
        break MISSING_BLOCK_LABEL_161;
_L15:
        return CGLIB$create$0$Proxy;
_L6:
        "equals(Ljava/lang/Object;)Z";
        equals();
        JVM INSTR ifeq 161;
           goto _L17 _L18
_L18:
        break MISSING_BLOCK_LABEL_161;
_L17:
        return CGLIB$equals$5$Proxy;
_L7:
        "toString()Ljava/lang/String;";
        equals();
        JVM INSTR ifeq 161;
           goto _L19 _L20
_L20:
        break MISSING_BLOCK_LABEL_161;
_L19:
        return CGLIB$toString$6$Proxy;
_L8:
        "hashCode()I";
        equals();
        JVM INSTR ifeq 161;
           goto _L21 _L22
_L22:
        break MISSING_BLOCK_LABEL_161;
_L21:
        return CGLIB$hashCode$3$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)
    {
        TargetClass$$EnhancerByCGLIB$$a0f953e6 targetclass$$enhancerbycglib$$a0f953e6 = (TargetClass$$EnhancerByCGLIB$$a0f953e6)obj;
        if(targetclass$$enhancerbycglib$$a0f953e6.CGLIB$BOUND) goto _L2; else goto _L1
_L1:
        Object obj1;
        targetclass$$enhancerbycglib$$a0f953e6.CGLIB$BOUND = true;
        obj1 = CGLIB$THREAD_CALLBACKS.get();
        obj1;
        if(obj1 != null) goto _L4; else goto _L3
_L3:
        JVM INSTR pop ;
        CGLIB$STATIC_CALLBACKS;
        if(CGLIB$STATIC_CALLBACKS != null) goto _L4; else goto _L5
_L5:
        JVM INSTR pop ;
          goto _L2
_L4:
        (Callback[]);
        targetclass$$enhancerbycglib$$a0f953e6;
        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 TargetClass$$EnhancerByCGLIB$$a0f953e6();
    }

    public Object newInstance(Callback callback)
    {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[] {
            callback
        });
        CGLIB$SET_THREAD_CALLBACKS(null);
        return new TargetClass$$EnhancerByCGLIB$$a0f953e6();
    }

    public Object newInstance(Class aclass[], Object aobj[], Callback acallback[])
    {
        CGLIB$SET_THREAD_CALLBACKS(acallback);
        JVM INSTR new #2   <Class TargetClass$$EnhancerByCGLIB$$a0f953e6>;
        JVM INSTR dup ;
        aclass;
        aclass.length;
        JVM INSTR tableswitch 0 0: default 35
    //                   0 28;
           goto _L1 _L2
_L2:
        JVM INSTR pop ;
        TargetClass$$EnhancerByCGLIB$$a0f953e6();
          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 0: default 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 0: default 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$create$0$Method;
    private static final MethodProxy CGLIB$create$0$Proxy;
    private static final Object CGLIB$emptyArgs[];
    private static final Method CGLIB$update$1$Method;
    private static final MethodProxy CGLIB$update$1$Proxy;
    private static final Method CGLIB$finalize$2$Method;
    private static final MethodProxy CGLIB$finalize$2$Proxy;
    private static final Method CGLIB$hashCode$3$Method;
    private static final MethodProxy CGLIB$hashCode$3$Proxy;
    private static final Method CGLIB$clone$4$Method;
    private static final MethodProxy CGLIB$clone$4$Proxy;
    private static final Method CGLIB$equals$5$Method;
    private static final MethodProxy CGLIB$equals$5$Proxy;
    private static final Method CGLIB$toString$6$Method;
    private static final MethodProxy CGLIB$toString$6$Proxy;

    static 
    {
        CGLIB$STATICHOOK1();
    }

    public TargetClass$$EnhancerByCGLIB$$a0f953e6()
    {
        CGLIB$BIND_CALLBACKS(this);
    }
}

    看了这个反编译的代码不要凌乱啊

    

    目前对cglib生成代理类研究不深,先在此记录如何使用cglib生成代理类;

    cglib动态代理还有一个方面比jdk动态代理强大的地方就是:cglib允许为代理类的不同方法实现不同的代理

逻辑,实现代码如下:

	public Object getProxyInstance(Class<TargetClass> clazz) {
		enhance.setSuperclass(clazz);
//		enhance.setCallback(this);
		enhance.setCallbackFilter(new MyCallbackFilter());//给代理类设置callBackFilter
		enhance.setCallbacks(new Callback[]{new MyLazyLoader(), new MyFixedValue()});//设置对应的filter数组
		
		return enhance.create();
	}  

class MyCallbackFilter implements CallbackFilter {
	public int accept(Method method) {
		if ("create".equals(method.getName())) {
			return 0;//返回数字为代理类callBack数组的下标值,下标值对应的callBack就是代理类该方法使用的CallBack
		} else if ("update".equals(method.getName())) {
			return 1;
		}
		return 0;
	}

    public boolean equals(Object o) {
    	return false;
    }
}

    代理类可以设置一个CallBackFilter和一个CallBack数组,在CallBackFilter里定义每个方法使用CallBack数组里的CallBack,在对应的CallBack里定义方法的具体代理逻辑。

   

    jdk的动态代理无法实现上述功能。

   

     

分享到:
评论

相关推荐

    Spring框架中JDK动态代理和cglib动态代理

    Spring 框架中 JDK 动态代理和 CGLIB 动态代理是 Spring AOP 中一个非常重要的知识点。Spring AOP 框架会根据实际情况选择使用 JDK 的动态代理还是 CGLIB 的动态代理。 JDK 动态代理是 Java 自带的动态代理机制,它...

    浅谈JDK动态代理与CGLIB代理去区别

    本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中的选择。 首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象...

    Jdk动态代理和cglib动态代理原理

    - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    jdk和cglib动态代理的例子{jar包+源码}

    jdk和cglib动态代理的例子{jar包+源码} 解压:如有问题 用快压

    jdk与cglib动态代理与底层实现

    - **CGLIB代理**:CGLIB通过ASM生成一个继承自目标类的新类,这个新类覆盖了目标类的所有方法,并在这些方法内部调用拦截器链。在运行时,这个新类的实例作为代理对象。 5. **优缺点**: - JDK代理简单易用,但...

    java代理机制 JDK动态代理和cglib代理 详解

    本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...

    Jdk动态代理,cglib动态代理,反射和拦截器(链)示例

    本资源提供的示例涵盖了这些核心概念,通过JDK动态代理、CGLIB动态代理以及拦截器链的实践,帮助开发者深入理解并掌握这些技术。 首先,让我们来探讨JDK动态代理。Java标准库中的`java.lang.reflect.Proxy`类和`...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...

    jdk 的动态代理和CGLIB代理

    jdk 的动态代理和CGLIB代理

    JDK动态代理和CGLIB代理

    JDK动态代理和CGLIB代理是两种常用的实现方式。 首先,我们来看看JDK动态代理。JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象...

    输出JDK和CGLib动态代理产生的class文件.zip

    2. CGLib代理项目: - src/main/java:包含目标类 - target/classes:编译后的class文件,包括目标类的class文件,以及由CGLib生成的子类class文件 - 测试代码:展示如何使用Enhancer创建代理对象并调用方法 这...

    jdk动态代理和CGlib动态代理

    JDK动态代理和CGlib动态代理是Java中实现这一目标的两种主要方式。 ### JDK动态代理 JDK动态代理基于Java的接口实现。如果一个类实现了至少一个接口,我们就可以为这个类创建一个动态代理。动态代理通过`java.lang....

    JDK动态代理和Cglib动态代理实例源码

    本篇将详细探讨JDK动态代理和Cglib动态代理,并通过源码实例来加深理解。 首先,JDK动态代理是Java内置的一种机制,它依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类...

    CGlib实现动态代理(承接上面JDK实现动态代理)

    与JDK的动态代理不同,JDK代理基于接口,如果目标类没有实现接口,就无法使用JDK的动态代理。而CGlib则无需目标类实现任何接口,因此它的应用范围更广。 以下是使用CGlib实现动态代理的关键步骤: 1. 引入依赖:在...

    静态代理、jdk动态代理、cglib动态代理

    Cglib 动态代理的实现方式是:我们首先需要定义一个类,然后使用 Cglib 库来生成该类的代理对象,该代理对象将拦截对被代理对象的所有方法调用,并控制对被代理对象的访问。 Cglib 动态代理的优点是:它的实现方式...

    JDK和CGlib分别实现的动态代理源代码

    JDK和CGlib是两种常用的动态代理实现方式,它们各自有不同的特性和使用场景。 首先,我们来详细了解一下JDK动态代理。JDK动态代理基于接口实现,它要求被代理的对象必须实现至少一个接口。通过`java.lang.reflect....

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最基础的代理实现方式。在静态代理中,我们需要创建一个代理类,这个代理类与原始类(被代理类)...

    CGLIB 和 JDK生成动态代理类的区别

    CGLIB和JDK动态代理是两种常用的实现方式,它们各有优缺点,适用于不同的场景。下面将详细探讨这两种动态代理的区别。 首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....

    JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)

    Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于接口实现,也就是说,被代理的对象必须实现至少一个接口。代理机制的核心是`java.lang.reflect.Proxy`类和...

Global site tag (gtag.js) - Google Analytics