动态代理:Cglib原理讲解

前言

CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。生成的代理类会继承被代理类,并重载其所有的方法。使用Cglib代理会生成三个代理类,继承目标类的代理类、继承FastClass的目标类、继承FastClss的代理类。

正文

我们要想了解其原理,先从生成的代理文件入手,看其结构特点。

测试用例

编写目标类(被代理类)

public class Book {
	public void read(){
		System.out.println("read");
	}
}

自定义方法拦截器

public class MyCglib implements MethodInterceptor {
	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
	 	System.out.println("增强");
		Object o1 = methodProxy.invokeSuper(o, objects);
		return o1;
	}
}
public class CglibTest {
	public static void main(String[] args) {
		//指定代理文件生成位置
		System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:");
		//通过Cglib
		Enhancer enhancer=new Enhancer();
		//设置父类类型
		enhancer.setSuperclass(Book.class);
		//设置回调接口
		enhancer.setCallback(new MyCglib());
		Book o = (Book) enhancer.create();
		o.read();
	}
}

结果分析

运行以上测试用例后,查看生成的类目录,可以看到生成了3个.class字节码代理文件。
代理类:



import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class Book$$EnhancerByCGLIB$$7c19c0f5 extends Book 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 MethodInterceptor CGLIB$CALLBACK_0;
    private static Object CGLIB$CALLBACK_FILTER;
    private static final Method CGLIB$read$0$Method;
    private static final MethodProxy CGLIB$read$0$Proxy;
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$equals$1$Method;
    private static final MethodProxy CGLIB$equals$1$Proxy;
    private static final Method CGLIB$toString$2$Method;
    private static final MethodProxy CGLIB$toString$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;

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("proxy.cglib.Book$$EnhancerByCGLIB$$7c19c0f5");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        CGLIB$read$0$Method = ReflectUtils.findMethods(new String[]{"read", "()V"}, (var1 = Class.forName("proxy.cglib.Book")).getDeclaredMethods())[0];
        CGLIB$read$0$Proxy = MethodProxy.create(var1, var0, "()V", "read", "CGLIB$read$0");
    }

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

    public final void read() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$read$0$Method, CGLIB$emptyArgs, CGLIB$read$0$Proxy);
        } else {
            super.read();
        }
    }

    final boolean CGLIB$equals$1(Object var1) {
        return super.equals(var1);
    }

    public final boolean equals(Object var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
            return var2 == null ? false : (Boolean)var2;
        } else {
            return super.equals(var1);
        }
    }

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

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
    }

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

    public final int hashCode() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.hashCode();
        }
    }

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

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
    }

    public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
        String var10000 = var0.toString();
        switch(var10000.hashCode()) {
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return CGLIB$clone$4$Proxy;
            }
            break;
        case 1080349215:
            if (var10000.equals("read()V")) {
                return CGLIB$read$0$Proxy;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return CGLIB$equals$1$Proxy;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return CGLIB$toString$2$Proxy;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return CGLIB$hashCode$3$Proxy;
            }
        }

        return null;
    }

    public Book$$EnhancerByCGLIB$$7c19c0f5() {
        CGLIB$BIND_CALLBACKS(this);
    }

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

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

    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        Book$$EnhancerByCGLIB$$7c19c0f5 var1 = (Book$$EnhancerByCGLIB$$7c19c0f5)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
        }

    }

    public Object newInstance(Callback[] var1) {
        CGLIB$SET_THREAD_CALLBACKS(var1);
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }

    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        Book$$EnhancerByCGLIB$$7c19c0f5 var10000 = new Book$$EnhancerByCGLIB$$7c19c0f5;
        switch(var1.length) {
        case 0:
            var10000.<init>();
            CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
            return var10000;
        default:
            throw new IllegalArgumentException("Constructor not found");
        }
    }

    public Callback getCallback(int var1) {
        CGLIB$BIND_CALLBACKS(this);
        MethodInterceptor var10000;
        switch(var1) {
        case 0:
            var10000 = this.CGLIB$CALLBACK_0;
            break;
        default:
            var10000 = null;
        }

        return var10000;
    }

    public void setCallback(int var1, Callback var2) {
        switch(var1) {
        case 0:
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
        default:
        }
    }

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

    public void setCallbacks(Callback[] var1) {
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
    }

    static {
        CGLIB$STATICHOOK1();
    }
}

目标类FastClass:

import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;

public class Book$$FastClassByCGLIB$$236a9cb6 extends FastClass {
    public Book$$FastClassByCGLIB$$236a9cb6(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case 1080349215:
            if (var10000.equals("read()V")) {
                return 0;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 1;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 2;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 3;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 2;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 1;
                    }
                }
            }
            break;
        case 3496342:
            if (var1.equals("read")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
        }

        return -1;
    }

    public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }

    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        Book var10000 = (Book)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                var10000.read();
                return null;
            case 1:
                return new Boolean(var10000.equals(var3[0]));
            case 2:
                return var10000.toString();
            case 3:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        Book var10000 = new Book;
        Book var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.<init>();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public int getMaxIndex() {
        return 3;
    }
}

代理类FastClass:

import java.lang.reflect.InvocationTargetException;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.reflect.FastClass;
import proxy.cglib.Book..EnhancerByCGLIB..7c19c0f5;

public class Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900 extends FastClass {
    public Book$$EnhancerByCGLIB$$7c19c0f5$$FastClassByCGLIB$$e9e27900(Class var1) {
        super(var1);
    }

    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -1882565338:
            if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
                return 18;
            }
            break;
        case -1870561232:
            if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
                return 14;
            }
            break;
        case -1745842178:
            if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case -1641413109:
            if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case -1593131472:
            if (var10000.equals("CGLIB$read$0()V")) {
                return 20;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 15;
            }
            break;
        case -1411842725:
            if (var10000.equals("CGLIB$hashCode$3()I")) {
                return 19;
            }
            break;
        case -1034266769:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 13;
            }
            break;
        case -1025895669:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
                return 12;
            }
            break;
        case -988317324:
            if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 5;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return 3;
            }
            break;
        case 610042816:
            if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case 1080349215:
            if (var10000.equals("read()V")) {
                return 7;
            }
            break;
        case 1132856532:
            if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
                return 10;
            }
            break;
        case 1246779367:
            if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
                return 8;
            }
            break;
        case 1306468936:
            if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
                return 16;
            }
            break;
        case 1364367423:
            if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
                return 11;
            }
            break;
        case 1800494055:
            if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
                return 17;
            }
            break;
        case 1826985398:
            if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
                return 0;
            }
            break;
        case 1913648695:
            if (var10000.equals("toString()Ljava/lang/String;")) {
                return 1;
            }
            break;
        case 1984935277:
            if (var10000.equals("hashCode()I")) {
                return 2;
            }
        }

        return -1;
    }

    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -1776922004:
            if (var1.equals("toString")) {
                switch(var2.length) {
                case 0:
                    return 1;
                }
            }
            break;
        case -1295482945:
            if (var1.equals("equals")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 0;
                    }
                }
            }
            break;
        case -1053468136:
            if (var1.equals("getCallbacks")) {
                switch(var2.length) {
                case 0:
                    return 10;
                }
            }
            break;
        case -124978609:
            if (var1.equals("CGLIB$equals$1")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 18;
                    }
                }
            }
            break;
        case -60403779:
            if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 13;
                    }
                }
            }
            break;
        case -29025555:
            if (var1.equals("CGLIB$hashCode$3")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        case 3496342:
            if (var1.equals("read")) {
                switch(var2.length) {
                case 0:
                    return 7;
                }
            }
            break;
        case 85179481:
            if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 12;
                    }
                }
            }
            break;
        case 94756189:
            if (var1.equals("clone")) {
                switch(var2.length) {
                case 0:
                    return 3;
                }
            }
            break;
        case 147696667:
            if (var1.equals("hashCode")) {
                switch(var2.length) {
                case 0:
                    return 2;
                }
            }
            break;
        case 161998109:
            if (var1.equals("CGLIB$STATICHOOK1")) {
                switch(var2.length) {
                case 0:
                    return 15;
                }
            }
            break;
        case 485510949:
            if (var1.equals("CGLIB$read$0")) {
                switch(var2.length) {
                case 0:
                    return 20;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 9;
                    }
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
                        return 14;
                    }
                }
            }
            break;
        case 1543336189:
            if (var1.equals("CGLIB$toString$2")) {
                switch(var2.length) {
                case 0:
                    return 16;
                }
            }
            break;
        case 1811874389:
            if (var1.equals("newInstance")) {
                switch(var2.length) {
                case 1:
                    String var10001 = var2[0].getName();
                    switch(var10001.hashCode()) {
                    case -1997738671:
                        if (var10001.equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                            return 4;
                        }
                        break;
                    case 1364160985:
                        if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
                            return 6;
                        }
                    }
                case 2:
                default:
                    break;
                case 3:
                    if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
                        return 5;
                    }
                }
            }
            break;
        case 1817099975:
            if (var1.equals("setCallback")) {
                switch(var2.length) {
                case 2:
                    if (var2[0].getName().equals("int") && var2[1].getName().equals("org.springframework.cglib.proxy.Callback")) {
                        return 8;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 11;
                    }
                }
            }
            break;
        case 1951977610:
            if (var1.equals("CGLIB$clone$4")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
        }

        return -1;
    }

    public int getIndex(Class[] var1) {
        switch(var1.length) {
        case 0:
            return 0;
        default:
            return -1;
        }
    }

    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        7c19c0f5 var10000 = (7c19c0f5)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
            case 0:
                return new Boolean(var10000.equals(var3[0]));
            case 1:
                return var10000.toString();
            case 2:
                return new Integer(var10000.hashCode());
            case 3:
                return var10000.clone();
            case 4:
                return var10000.newInstance((Callback[])var3[0]);
            case 5:
                return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
            case 6:
                return var10000.newInstance((Callback)var3[0]);
            case 7:
                var10000.read();
                return null;
            case 8:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 9:
                var10000.setCallbacks((Callback[])var3[0]);
                return null;
            case 10:
                return var10000.getCallbacks();
            case 11:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 12:
                7c19c0f5.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 13:
                7c19c0f5.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 14:
                return 7c19c0f5.CGLIB$findMethodProxy((Signature)var3[0]);
            case 15:
                7c19c0f5.CGLIB$STATICHOOK1();
                return null;
            case 16:
                return var10000.CGLIB$toString$2();
            case 17:
                return var10000.CGLIB$clone$4();
            case 18:
                return new Boolean(var10000.CGLIB$equals$1(var3[0]));
            case 19:
                return new Integer(var10000.CGLIB$hashCode$3());
            case 20:
                var10000.CGLIB$read$0();
                return null;
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        7c19c0f5 var10000 = new 7c19c0f5;
        7c19c0f5 var10001 = var10000;
        int var10002 = var1;

        try {
            switch(var10002) {
            case 0:
                var10001.<init>();
                return var10000;
            }
        } catch (Throwable var3) {
            throw new InvocationTargetException(var3);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }

    public int getMaxIndex() {
        return 20;
    }
}

1、我们可以看到代理类中拥有被代理类的所有的方法,在代理类被实例化后后执行静态代码块的内容,会对被代理类的每个方法进行解析,计算出代理类和被代理类方法名称的Signature值,并封装成MethodProxy对象;
创建MethodProxy过程见方法1详解
创建代理类过程见方法4详解

2、在代理类的方法里面会调用我们自定义的方法拦截器,并把代理类对象、方法名称解析对应的MethodProxy、方法对象传递进去,最终由自定义方法拦截器来调用。

3、自定义方法拦截器中的intercept方法,我们可以根据传递进来的MethodProxy决定调用逻辑,如MethodProxy的invokeSuper会调用父类方法。

4、MethodProxy的invokeSuper方法(见方法2详解)会传递代理类对象及其要执行对应方法参数。invokeSuper流程中会生成继承FastClass的被代理类跟代理类共两个.class文件。其中有两个重要的方法getIndex和invoke方法;

5、getIndex方法会根据步骤1中方法名计算出Signature来匹配方法对应的key,根据key去匹配invoke方法决定最终调用哪个方法。这个步骤没有涉及反射也是与JDK动态代理不同的地方。

方法1:MethodProxy类的create方法

	public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
		MethodProxy proxy = new MethodProxy();
		//计算的是被代理类的
		proxy.sig1 = new Signature(name1, desc);
		//计算的是代理类的
		proxy.sig2 = new Signature(name2, desc);
		proxy.createInfo = new CreateInfo(c1, c2);
		return proxy;
	}

方法2:MethodProxy类的invoke方法

MethodProxy

	public Object invokeSuper(Object obj, Object[] args) throws Throwable {
		try {
			//这个过程会创建类型为代理类跟被代理的FastClass类
			init();
			//获取init中封装好的信息
			FastClassInfo fci = fastClassInfo;
			//调用被代理类的方法,传递方法index下标,通过该下标会在FastClass找出对应的方法并执行
			return fci.f2.invoke(fci.i2, obj, args);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
		catch (IllegalArgumentException ex) {
			if (fastClassInfo.i1 < 0)
				throw new IllegalArgumentException("Protected method: " + sig1);
			throw ex;
		}
	}

init(),见方法3详解

方法3:MethodProxy类的init方法

	private void init() {
		/*
		 * Using a volatile invariant allows us to initialize the FastClass and
		 * method index pairs atomically.
		 *
		 * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this
		 * code could allow fastClassInfo to be instantiated more than once, which
		 * appears to be benign.
		 */
		if (fastClassInfo == null) {
			synchronized (initLock) {
				//判断是否缓存过
				if (fastClassInfo == null) {
					CreateInfo ci = createInfo;

					FastClassInfo fci = new FastClassInfo();
					//生成被代理类的FastClass对象
					fci.f1 = helper(ci, ci.c1);
					//生成代理类的FastClass对象
					fci.f2 = helper(ci, ci.c2);
					//根据sig值计算出该方法名在被代理类FastClass中对应的下标
					fci.i1 = fci.f1.getIndex(sig1);
					//根据sig值计算出该方法名在代理类FastClass中对应的下标
					fci.i2 = fci.f2.getIndex(sig2);
					fastClassInfo = fci;
					createInfo = null;
				}
			}
		}
	}

生成FastClass对象的过程跟生成代理类过程有点类似,这里不做讲解,后面会讲解代理类的创建过程,过程都差不多。

方法4:enhancer.create方法

代理类会在我们测试用例中调用enhancer.create()方法时进行创建。

	public Object create() {
		classOnly = false;
		argumentTypes = null;
		return createHelper();
	}
	private Object createHelper() {
		//校验callbackTypes、filter是否为空,以及为空时的处理
		preValidate();
		//通过newInstance方法来创建EnhancerKey对象.KEY_FACTORY对象在测试用例new Enhance流程中会被动态代理创建
		Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
				ReflectUtils.getNames(interfaces),
				filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
				callbackTypes,
				useFactory,
				interceptDuringConstruction,
				serialVersionUID);
		this.currentKey = key;
		//开始创建
		Object result = super.create(key);
		return result;
	}

super.create(key),见方法5详解

方法5:create

	protected Object create(Object key) {
		try {
			//获取类加载器
			ClassLoader loader = getClassLoader();
			//尝试从缓存中获取当前类加载器对应的ClassLoaderData对象
			Map<ClassLoader, ClassLoaderData> cache = CACHE;
			ClassLoaderData data = cache.get(loader);
			//获取不到则创建
			if (data == null) {
				synchronized (AbstractClassGenerator.class) {
					cache = CACHE;
					data = cache.get(loader);
					if (data == null) {
						//创建ClassLoaderData并加入newCache缓存中
						Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
						data = new ClassLoaderData(loader);
						newCache.put(loader, data);
						CACHE = newCache;
					}
				}
			}
			this.key = key;
			//生成代理对象
			Object obj = data.get(this, getUseCache());
			//如果类似是Class对象,则进行实例化
			if (obj instanceof Class) {
				return firstInstance((Class) obj);
			}
			return nextInstance(obj);
		}
		catch (RuntimeException | Error ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CodeGenerationException(ex);
		}
	}

new ClassLoaderData(loader),见方法6详解

data.get(this, getUseCache()),见方法7详解

方法6:new ClassLoaderData(loader)

这个类比较长,这里我就把比较重要的两个方法进行讲解,这里

protected static class ClassLoaderData {

		private final Set<String> reservedClassNames = new HashSet<String>();

		/**
		 * {@link AbstractClassGenerator} here holds "cache key" (e.g. {@link org.springframework.cglib.proxy.Enhancer}
		 * configuration), and the value is the generated class plus some additional values
		 * (see {@link #unwrapCachedValue(Object)}.
		 * 

The generated classes can be reused as long as their classloader is reachable.

*

Note: the only way to access a class is to find it through generatedClasses cache, thus * the key should not expire as long as the class itself is alive (its classloader is alive).

*/
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses; /** * Note: ClassLoaderData object is stored as a value of {@code WeakHashMap} thus * this classLoader reference should be weak otherwise it would make classLoader strongly reachable * and alive forever. * Reference queue is not required since the cleanup is handled by {@link WeakHashMap}. */ private final WeakReference<ClassLoader> classLoader; private final Predicate uniqueNamePredicate = new Predicate() { public boolean evaluate(Object name) { return reservedClassNames.contains(name); } }; //这里存的是Function函数,后续步骤中会调用 private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() { public Object apply(AbstractClassGenerator gen) { return gen.key; } }; public ClassLoaderData(ClassLoader classLoader) { if (classLoader == null) { throw new IllegalArgumentException("classLoader == null is not yet supported"); } this.classLoader = new WeakReference<ClassLoader>(classLoader); //这里创建的是函数式接口,后续步骤中会调用 Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() { //创建代理类 public Object apply(AbstractClassGenerator gen) { Class klass = gen.generate(ClassLoaderData.this); return gen.wrapCachedClass(klass); } }; generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load); } public ClassLoader getClassLoader() { return classLoader.get(); } public void reserveName(String name) { reservedClassNames.add(name); } public Predicate getUniqueNamePredicate() { return uniqueNamePredicate; } public Object get(AbstractClassGenerator gen, boolean useCache) { if (!useCache) { return gen.generate(ClassLoaderData.this); } else { Object cachedValue = generatedClasses.get(gen); return gen.unwrapCachedValue(cachedValue); } } }

方法7:get

		public Object get(AbstractClassGenerator gen, boolean useCache) {
			//如果没有使用缓存,则直接调用创建代理类方法
			if (!useCache) {
				return gen.generate(ClassLoaderData.this);
			}
			else {
				//这里会调用方法6中创建的两个Function函数式类
				Object cachedValue = generatedClasses.get(gen);
				return gen.unwrapCachedValue(cachedValue);
			}
		}
    public V get(K key) {
    		//调用步骤6中GET_KEY函数式类
        KK cacheKey = this.keyMapper.apply(key);
        //尝试从缓存中获取代理类对象
        Object v = this.map.get(cacheKey);
        //如果获取不到则创建代理类
        return v != null && !(v instanceof FutureTask) ? v : this.createEntry(key, cacheKey, v);
    }

this.createEntry(key, cacheKey, v),见方法8详解

方法8:createEntry

protected V createEntry(final K key, KK cacheKey, Object v) {
        boolean creator = false;
        FutureTask task;
        Object result;
        if (v != null) {
            task = (FutureTask)v;
        } else {
        	//创建线程
            task = new FutureTask(new Callable<V>() {
                public V call() throws Exception {
                	//调用方法6中写好的Function函数
                    return LoadingCache.this.loader.apply(key);
                }
            });
            //将线程加入缓存中
            result = this.map.putIfAbsent(cacheKey, task);
            if (result == null) {
                creator = true;
                 //开启线程
                task.run();
            } else {
                if (!(result instanceof FutureTask)) {
                    return result;
                }

                task = (FutureTask)result;
            }
        }

        try {
            result = task.get();
        } catch (InterruptedException var9) {
            throw new IllegalStateException("Interrupted while loading cache item", var9);
        } catch (ExecutionException var10) {
            Throwable cause = var10.getCause();
            if (cause instanceof RuntimeException) {
                throw (RuntimeException)cause;
            }

            throw new IllegalStateException("Unable to load cache item", cause);
        }

        if (creator) {
            this.map.put(cacheKey, result);
        }

        return result;
    }

LoadingCache.this.loader.apply(key),见方法9详解

方法9:apply

调用函数式接口

	public Object apply(AbstractClassGenerator gen) {
		Class klass = gen.generate(ClassLoaderData.this);
		return gen.wrapCachedClass(klass);
	}
	protected Class generate(ClassLoaderData data) {
		validate();
		//设置代理类名称前缀
		if (superclass != null) {
			setNamePrefix(superclass.getName());
		}
		else if (interfaces != null) {
			setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
		}
		return super.generate(data);
	}
	protected Class generate(ClassLoaderData data) {
		Class gen;
		Object save = CURRENT.get();
		//将当前代理类生成器存入线程中
		CURRENT.set(this);
		try {
			//获取类加载器
			ClassLoader classLoader = data.getClassLoader();
			if (classLoader == null) {
				throw new IllegalStateException("ClassLoader is null while trying to define class " +
						getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
						"Please file an issue at cglib's issue tracker.");
			}
			synchronized (classLoader) {
			  //生成代理类名称
				String name = generateClassName(data.getUniqueNamePredicate());
				//缓存中存入这个名称
				data.reserveName(name);
				//当前代理类设置了吗
				this.setClassName(name);
			}
			if (attemptLoad) {
				try {
				//尝试使用类加载器获取代理对象,获取到则返回
					gen = classLoader.loadClass(getClassName());
					return gen;
				}
				catch (ClassNotFoundException e) {
					// ignore
				}
			}
			//生成代理类字节码流
			byte[] b = strategy.generate(this);
			//获取字节码代表的代理类名称
			String className = ClassNameReader.getClassName(new ClassReader(b));
			ProtectionDomain protectionDomain = getProtectionDomain();
			synchronized (classLoader) { // just in case
				// SPRING PATCH BEGIN
				gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
				// SPRING PATCH END
			}
			return gen;
		}
		catch (RuntimeException | Error ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CodeGenerationException(ex);
		}
		finally {
			CURRENT.set(save);
		}
	}

strategy.generate(this),见方法10详解

方法10:generate

    public byte[] generate(ClassGenerator cg) throws Exception {
        DebuggingClassWriter cw = this.getClassVisitor();
        this.transform(cg).generateClass(cw);
        return this.transform(cw.toByteArray());
    }
	public void generateClass(ClassVisitor v) throws Exception {
		//如果目标类存在则以目标类为父类,否则以Object为父类
		Class sc = (superclass == null) ? Object.class : superclass;

		if (TypeUtils.isFinal(sc.getModifiers()))
			throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
	  //获取父类的所有构造函数
		List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
		//去掉private不能被继承的构造函数
		filterConstructors(sc, constructors);

		// Order is very important: must add superclass, then
		// its superclass chain, then each interface and
		// its superinterfaces.
		//存放代理类的所有方法
		List actualMethods = new ArrayList();
		List interfaceMethods = new ArrayList();
		final Set forcePublic = new HashSet();
		//获取其父类的所有方法,包括父类的父类... 父类的所有接口包含的方法,过滤掉不能被继承的方法
		getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
		//所有方法进行修饰符处理
		List methods = CollectionUtils.transform(actualMethods, new Transformer() {
			public Object transform(Object value) {
				Method method = (Method) value;
				int modifiers = Constants.ACC_FINAL
						| (method.getModifiers()
						& ~Constants.ACC_ABSTRACT
						& ~Constants.ACC_NATIVE
						& ~Constants.ACC_SYNCHRONIZED);
				if (forcePublic.contains(MethodWrapper.create(method))) {
					modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
				}
				return ReflectUtils.getMethodInfo(method, modifiers);
			}
		});
		//创建写日期
		ClassEmitter e = new ClassEmitter(v);
		if (currentData == null) {
			e.begin_class(Constants.V1_8,
					Constants.ACC_PUBLIC,
					getClassName(),
					Type.getType(sc),
					(useFactory ?
							TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
							TypeUtils.getTypes(interfaces)),
					Constants.SOURCE_FILE);
		}
		else {
			e.begin_class(Constants.V1_8,
					Constants.ACC_PUBLIC,
					getClassName(),
					null,
					new Type[]{FACTORY},
					Constants.SOURCE_FILE);
		}
		List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());

		e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
		e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
		if (!interceptDuringConstruction) {
			e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
		}
		e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
		e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
		if (serialVersionUID != null) {
			e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
		}

		for (int i = 0; i < callbackTypes.length; i++) {
			e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
		}
		// This is declared private to avoid "public field" pollution
		e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);

		if (currentData == null) {
			//写入方法
			emitMethods(e, methods, actualMethods);
			//写入构造方法
			emitConstructors(e, constructorInfo);
		}
		else {
			emitDefaultConstructor(e);
		}
		//写入回调方法
		emitSetThreadCallbacks(e);
		//写入静态代理块
		emitSetStaticCallbacks(e);
		//绑定回调方法
		emitBindCallbacks(e);

		if (useFactory || currentData != null) {
			int[] keys = getCallbackKeys();
			emitNewInstanceCallbacks(e);
			emitNewInstanceCallback(e);
			emitNewInstanceMultiarg(e, constructorInfo);
			emitGetCallback(e, keys);
			emitSetCallback(e, keys);
			emitGetCallbacks(e);
			emitSetCallbacks(e);
		}

		e.end_class();
	}

到这里整个代理类创建过程就差不多告一段落了。

总结

Cglib动态代理不需要被代理类实现接口,根据原理我们知道生成的代理类是继承了被代理类,而且其方法调用方法是使用FastClass,这与JDK动态代理的反射有比较大的区别。

JDK和CGLIB动态代理的区别:

  • JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

  • CGLIB代理使用字节码处理框架ASM,对代理对象类的class文件加载进来,通过修改字节码生成子类。

  • JDK创建代理对象效率较高,执行效率较低;

  • CGLIB创建代理对象效率较低,执行效率高。

  • JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;

  • CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不- 能代理final修饰的类。

JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:

  1. 实现InvocationHandler接口,重写invoke()
  2. 使用Proxy.newProxyInstance()产生代理对象
  3. 被代理的对象必须要实现接口

CGLib 必须依赖于CGLib的类库,需要满足以下要求:

  1. 实现MethodInterceptor接口,重写intercept()
  2. 使用Enhancer对象.create()产生代理对象

你可能感兴趣的:(原理学习,Java,java,开发语言)