JDK动态代理和CGLIB代理源码分析

目录

一、使用方式

1.业务方法类

2.实现代理方法

3.使用场景分析

3.1.使用CGLIB代理执行非接口实现类HelloWorld

3.2.使用CGLIB代理执行接口实现类UserServiceImpl

3.3.使用JDK动态代理执行接口实现类UserServiceImpl

3.1.使用JDK动态代理执行非接口实现类HelloWorld

二、源码分析

1.JDK动态代理源码分析

1.1创建代理对象

1.2调用代理对象

2.CGLIB代理源码分析

2.1创建代理对象

2.2调用代理对象

2.3类MethodProxy中invoke和invokeSuper执行源码分析及区别

三、总结


JDK动态代理和CGLIB代理算是java的基础知识点,在面试场合经常被问到,他们的使用方式、原理及区别是怎样的呢,下面我们一起来解读下。

以下本次研究的涉及到的版本:

  • jdk1.8

  • cglib3.3.0

cglib是一个强大的、高性能、高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口,cglib封装了asm,可以在运行期动态生成新的 class,Hibernate和Spring都用到过它。cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。

ASM是一个Java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。Java class被存储在严格格式定义的.class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

一、使用方式

需注意,正常我们谈jdk动态代理和cglib代理时,使用比较多的场景是在spring的aop里,但在spring的aop中最终实现的仍是jdk和cglib提供的基础方法,所以我们还是先从基础方法说起,那么在spring中就更容易理解了。

1.业务方法类

首先,创建一个没有实现接口的类HelloWorld,

package com.test.proxy;
​
public class HelloWorld {
    public void sayHello(){
        System.out.println("say HelloWorld");
    }
}

创建一个接口

package com.test.proxy;
​
public interface UserService {
    void addUser();
}

创建一个实现类

package com.test.proxy;
​
public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("register algo");
    }
}

2.实现代理方法

实现JDK动态代理方法,

package com.test.proxy;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
​
public class JDKProxy implements InvocationHandler {
​
    // 需要代理的目标对象
    private Object targetObject;
​
    /**
     * 创建代理对象
     * @param targetObject
     * @return
     */
    public Object createProxy(Object targetObject) {
        this.targetObject = targetObject;
        // 返回代理对象
        Object proxyObj =  Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(), this);
        return proxyObj;
    }
​
    /**
     * invoke方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 检查权限
        checkPopedom();
        Object ret = null;
        try {
            // 前置通知
            before();
            // 调用invoke方法
            ret  = method.invoke(targetObject, args);
            // 后置通知
            after();
        } catch (Exception e) {
            // 异常通知
            exception();
        } finally {
            // 方法返回前通知
            beforeReturning();
        }
        return ret;
    }
​
    private void before() {
        System.out.println("JDKProxy:before method invoke...");
    }
    private void after() {
        System.out.println("JDKProxy:after method invoke...");
    }
    private void exception() {
        System.out.println("JDKProxy:exception method invoke...");
    }
    private void beforeReturning() {
        System.out.println("JDKProxy:beforeReturning method invoke...");
    }
    private void checkPopedom() {// 模拟检查权限的例子
        System.out.println("JDKProxy:检查权限  checkPopedom()!");
    }
​
}

实现CGLIB代理方法,

package com.test.proxy;
​
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
​
import java.lang.reflect.Method;
​
public class CGLibProxy implements MethodInterceptor {
​
    // CGLib需要代理的目标对象
    private Object targetObject;
​
    /**
     * 创建代理对象
     * @param obj
     * @return
     */
    public Object createProxy(Object obj) {
        this.targetObject = obj;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        Object proxyObj = enhancer.create();
        return proxyObj;
    }
​
    /**
     * intercept方法
     * @param proxy
     * @param method
     * @param args
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //  检查权限
        checkPopedom();
        Object obj = null;
        try {
            // 前置通知
            before();
            // 调用invoke方法
            obj = method.invoke(targetObject, args);
            // 后置通知
            after();
        } catch (Exception e) {
            // 异常通知
            exception();
        } finally {
            // 方法返回前通知
            beforeReturning();
        }
        return obj;
    }
​
    private void before() {
        System.out.println("CGLibProxy:before method invoke...");
    }
    private void after() {
        System.out.println("CGLibProxy:after method invoke...");
    }
    private void exception() {
        System.out.println("CGLibProxy:exception method invoke...");
    }
    private void beforeReturning() {
        System.out.println("CGLibProxy:beforeReturning method invoke...");
    }
    private void checkPopedom() {
        System.out.println("CGLibProxy:检查权限  checkPopedom()!");
    }
​
}

由上可以看出,

JDK动态代理方法,需要实现InvocationHandler接口,并重写invoke方法(可以在invoke()方法进行面向切面的处理,调用相应通知),而创建代理对象是通过Proxy类的newProxyInstance方法实现的,invoke方法的作用是,调用的时候,执行切面逻辑,以及通过Method的invoke的反射机制调用目标类的原始方法。

CGLIB代理方法,需要实现MethodInterceptor接口,并重写intercept方法(可以在intercept()方法进行面向切面的处理,调用相应通知),而创建代理对象是通过Enhancer类实现的,intercept方法的作用是,调用的时候,执行切面逻辑,以及通过Method的invoke的反射机制调用目标类的原始方法,或者用MethodProxy.invokeSuper方法,通过fastclass机制直接调用目标类的原始方法。

3.使用场景分析

其实,两个代理方法都可以完成代理的工作,那么结合具体场景分析下区别,

3.1.使用CGLIB代理执行非接口实现类HelloWorld

package com.test.proxy;
​
import net.sf.cglib.core.DebuggingClassWriter;
​
public class ProxyPerformanceTest {
    public static void main(String[] args) {
        // 该方法是为了生成由CGLIB生成的代理对象CLASS文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
        System.out.println("-----------CGLibProxy not use interface start-------------");
        HelloWorld helloWorldCglib = (HelloWorld) new CGLibProxy().createProxy(new HelloWorld());
        helloWorldCglib.sayHello();
        System.out.println("-----------CGLibProxy not use interface end-------------");
    }
}

执行结果为,

-----------CGLibProxy not use interface start-------------
CGLIB debugging enabled, writing to 'D:\class'
CGLibProxy:检查权限  checkPopedom()!
CGLibProxy:before method invoke...
say HelloWorld
CGLibProxy:after method invoke...
CGLibProxy:beforeReturning method invoke...
-----------CGLibProxy not use interface end-------------

生成的代理class文件内容,

package com.test.proxy;
​
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
​
public class HelloWorld$$EnhancerByCGLIB$$74b9b49 extends HelloWorld 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$sayHello$0$Method;
    private static final MethodProxy CGLIB$sayHello$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$STATICHOOK2() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.test.proxy.HelloWorld$$EnhancerByCGLIB$$74b9b49");
        Class var1;
        CGLIB$sayHello$0$Method = ReflectUtils.findMethods(new String[]{"sayHello", "()V"}, (var1 = Class.forName("com.test.proxy.HelloWorld")).getDeclaredMethods())[0];
        CGLIB$sayHello$0$Proxy = MethodProxy.create(var1, var0, "()V", "sayHello", "CGLIB$sayHello$0");
        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");
    }
​
    final void CGLIB$sayHello$0() {
        super.sayHello();
    }
​
    public final void sayHello() {
        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$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
        } else {
            super.sayHello();
        }
    }
​
    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 1535311470:
            if (var10000.equals("sayHello()V")) {
                return CGLIB$sayHello$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 HelloWorld$$EnhancerByCGLIB$$74b9b49() {
        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) {
        HelloWorld$$EnhancerByCGLIB$$74b9b49 var1 = (HelloWorld$$EnhancerByCGLIB$$74b9b49)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);
        HelloWorld$$EnhancerByCGLIB$$74b9b49 var10000 = new HelloWorld$$EnhancerByCGLIB$$74b9b49();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
​
    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        HelloWorld$$EnhancerByCGLIB$$74b9b49 var10000 = new HelloWorld$$EnhancerByCGLIB$$74b9b49();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
​
    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        HelloWorld$$EnhancerByCGLIB$$74b9b49 var10000 = new HelloWorld$$EnhancerByCGLIB$$74b9b49;
        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$STATICHOOK2();
    }
}

由上可以看出,生成的代理对象是目标对象HelloWorld的子类,且实现了目标对象的sayHello方法,这里也间接说明了CGLIB不能代理final修饰的类或者方法。

3.2.使用CGLIB代理执行接口实现类UserServiceImpl

package com.test.proxy;
​
import net.sf.cglib.core.DebuggingClassWriter;
​
public class ProxyPerformanceTest {
​
    public static void main(String[] args) {
        // 该方法是为了生成由CGLIB生成的代理对象CLASS文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
        System.out.println("-----------CGLibProxy use interface start-------------");
        UserService userServiceCglib = (UserService) new CGLibProxy().createProxy(new UserServiceImpl());
        userServiceCglib.addUser();
        System.out.println("-----------CGLibProxy use interface end-------------");
    }
}

执行结果为,

-----------CGLibProxy use interface start-------------
CGLIB debugging enabled, writing to 'D:\class'
CGLibProxy:检查权限  checkPopedom()!
CGLibProxy:before method invoke...
register algo
CGLibProxy:after method invoke...
CGLibProxy:beforeReturning method invoke...
-----------CGLibProxy use interface end-------------

生成的代理class文件内容如下,

package com.test.proxy;
​
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
​
public class UserServiceImpl$$EnhancerByCGLIB$$519ec1cd extends UserServiceImpl 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$addUser$0$Method;
    private static final MethodProxy CGLIB$addUser$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("com.test.proxy.UserServiceImpl$$EnhancerByCGLIB$$519ec1cd");
        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$addUser$0$Method = ReflectUtils.findMethods(new String[]{"addUser", "()V"}, (var1 = Class.forName("com.test.proxy.UserServiceImpl")).getDeclaredMethods())[0];
        CGLIB$addUser$0$Proxy = MethodProxy.create(var1, var0, "()V", "addUser", "CGLIB$addUser$0");
    }
​
    final void CGLIB$addUser$0() {
        super.addUser();
    }
​
    public final void addUser() {
        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$addUser$0$Method, CGLIB$emptyArgs, CGLIB$addUser$0$Proxy);
        } else {
            super.addUser();
        }
    }
​
    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 1761046505:
            if (var10000.equals("addUser()V")) {
                return CGLIB$addUser$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 UserServiceImpl$$EnhancerByCGLIB$$519ec1cd() {
        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) {
        UserServiceImpl$$EnhancerByCGLIB$$519ec1cd var1 = (UserServiceImpl$$EnhancerByCGLIB$$519ec1cd)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);
        UserServiceImpl$$EnhancerByCGLIB$$519ec1cd var10000 = new UserServiceImpl$$EnhancerByCGLIB$$519ec1cd();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
​
    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        UserServiceImpl$$EnhancerByCGLIB$$519ec1cd var10000 = new UserServiceImpl$$EnhancerByCGLIB$$519ec1cd();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
​
    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        UserServiceImpl$$EnhancerByCGLIB$$519ec1cd var10000 = new UserServiceImpl$$EnhancerByCGLIB$$519ec1cd;
        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();
    }
}

由上可以看出,生成的代理对象是目标对象UserServiceImpl的子类,且实现了目标对象的addUser方法。

3.3.使用JDK动态代理执行接口实现类UserServiceImpl

package com.test.proxy;
​
import net.sf.cglib.core.DebuggingClassWriter;
​
public class ProxyPerformanceTest {
​
    public static void main(String[] args) {
        // 该方法是为了生成由JDK代理生成的代理对象CLASS文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
​
        System.out.println("-----------JDKProxy use interface start-------------");
        UserService userServiceJdk = (UserService) new JDKProxy().createProxy(new UserServiceImpl());
        userServiceJdk.addUser();
        System.out.println("-----------JDKProxy use interface end-------------");
    }
}

执行结果如下,

-----------JDKProxy use interface start-------------
JDKProxy:检查权限  checkPopedom()!
JDKProxy:before method invoke...
register algo
JDKProxy:after method invoke...
JDKProxy:beforeReturning method invoke...
-----------JDKProxy use interface end-------------

生成的代理class文件内容如下,

package com.sun.proxy;
​
import com.test.proxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
​
public final class $Proxy0 extends Proxy implements UserService {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3;
​
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
​
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
​
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
​
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
​
    public final void addUser() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
​
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("com.test.proxy.UserService").getMethod("addUser");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

由上可以看出,生成的代理类继承Proxy(默认),但是实现了UserService接口,并且重写了addUser方法。这里需要补充的一点是,因为jdk动态代理方法默认让代理对象继承Proxy,而java里是不支持多继承的,所以如果要通过jdk动态代理实现代理,那么目标对象必须实现接口才能被代理,我们可以通过3.4场景进行验证。

在重写的addUser方法里,通过super.h.invoke调用代理类JDKProxy中的invoke方法来完成的。

3.1.使用JDK动态代理执行非接口实现类HelloWorld

package com.test.proxy;
​
import net.sf.cglib.core.DebuggingClassWriter;
​
public class ProxyPerformanceTest {
​
    public static void main(String[] args) {
        // 该方法是为了生成由JDK代理生成的代理对象CLASS文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
​
        System.out.println("-----------JDKProxy not use interface start-------------");
        HelloWorld helloWorldJdk = (HelloWorld) new JDKProxy().createProxy(new HelloWorld());
        helloWorldJdk.sayHello();
        System.out.println("-----------JDKProxy not use interface end-------------");
    }
}

执行结果如下,

-----------JDKProxy not use interface start-------------
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.test.proxy.HelloWorld
    at com.test.proxy.ProxyPerformanceTest.main(ProxyPerformanceTest.java:12)

如上,创建代理对象是成功的,只是在强制把代理对象转换为HelloWorld的时候失败了,我们来看下实际生成的代理对象。如下,

package com.sun.proxy;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
​
public final class $Proxy1 extends Proxy {
    private static Method m1;
    private static Method m2;
    private static Method m0;
​
    public $Proxy1(InvocationHandler var1) throws  {
        super(var1);
    }
​
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
​
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
​
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
​
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

很清晰了,因为HelloWorld不是接口实现类,所以生成的代理对象没有实现或者继承HelloWorld,故转换成HelloWorld时,肯定是失败的。

二、源码分析

1.JDK动态代理源码分析

1.1创建代理对象

JDK动态代理创建代理对象通过Proxy.newProxyInstance方法完成,首先看下这个方法几个参数的意思。

  • loader:一个classloader对象,定义了由哪个classloader对象对生成的代理类进行加载。

  • interfaces: 一个interface对象数组,表示我们将要给我们的代理对象提供一组什么样的接口,如果我们提供了这样一个接口对象数组,那么也就是声明了代理类实现了这些接口,代理类就可以调用接口中声明的所有方法。

  • h: 一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用,会调用h里面的invoke方法去执行。

newProxyInstance源码如下,

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
    {
        // 校验InvocationHandler不能为空
        Objects.requireNonNull(h);
        // 克隆该类实现的所有接口
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        // 进行权限校验,非关键代码可以不用关心
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
​
        // 这个是关键代码,根据classloader、interfaces生成代理类字节码,直接生成的.class不是生成.java编译的
        Class<?> cl = getProxyClass0(loader, intfs);
​
        // 使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            // 获取代理类的构造函数,入参为InvocationHandler
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            // 判断代理类是否是Public的,不是public的则取消构造器验证权限限制
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        // 设置在使用构造器的时候不执行权限检查
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            // 通过构造函数实例化代理类,这里为什么用newInstance可以查下new和newInstance的区别,还有这里实例化的时候把h带进去了,
            // h是InvocationHandler,可以看jdk动态代理生成的代理类中构造函数是什么样的就知道为什么传h了
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

可以看出,生成代理对象分为以下三步:

第一步,通过classLoader,interfaces创建代理对象;

第二步,通过代理类Class获取入参为{InvocationHandler}的构造器;

第三步,通过构造器实例化代理对象。

其中,第一步最关键,getProxyClass0源码如下,

private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
    // 接口数量不能超过65535
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }
​
    // If the proxy class defined by the given loader implementing
    // the given interfaces exists, this will simply return the cached copy;
    // otherwise, it will create the proxy class via the ProxyClassFactory
    // 判断给定的代理类是否在缓存中存在,如果存在则直接返回副本,否则通过ProxyClassFactory创建
    return proxyClassCache.get(loader, interfaces);
}

这里我们重点关注代理类是如何生成的,缓存的机制先略过(不是本文重点),proxyClassCache.get里生成代理调用的是ProxyClassFactory的apply方法,源码如下,

private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // 代理类的前缀,所以为什么jdk动态代理生成的类都是$Proxy开头的
        private static final String proxyClassNamePrefix = "$Proxy";

        // 生成一个数字,保证唯一性,用于代理类的名称
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            // 遍历接口
            for (Class<?> intf : interfaces) {
                // 校验类加载器是否能通过接口名称加载该类,这个加载器是被代理目标类的加载器
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                // 校验是否是接口
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                // 校验接口是否重复
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // 定义代理类的包
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL; // 访问标志

            // 非public接口,代理类的包名与接口的包名相同
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // public代理接口,使用com.sun.proxy包名
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            // 为代理类生成名字
            // 如:com.sun.proxy.$Proxy0
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            // 生成代理对象的字节码,即class文件
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
            	// 使用类加载器将代理类的字节码文件加载到JVM中,native方法,然后返回代理类class对象
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

生成代理对象字节码的方法generateProxyClass,源码如下,

public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
    ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
    // 生成代理类的字节码
    final byte[] var4 = var3.generateClassFile();
    // 是否要将生成代理类的字节码文件保存到磁盘中,该变量可以通过系统属性设置
    if (saveGeneratedFiles) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                try {
                    int var1 = var0.lastIndexOf(46);
                    Path var2;
                    if (var1 > 0) {
                        Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                        Files.createDirectories(var3);
                        var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                    } else {
                        var2 = Paths.get(var0 + ".class");
                    }
                    // 将文件写入磁盘
                    Files.write(var2, var4, new OpenOption[0]);
                    return null;
                } catch (IOException var4x) {
                    throw new InternalError("I/O exception saving generated file: " + var4x);
                }
            }
        });
    }
​
    return var4;
}

以上就是jdk动态代理创建代理类文件的过程。

1.2调用代理对象

从第一部分的3.3示例中生成的代理类,可以看出,代理类中重写的业务里的addUser方法,实际执行该方法时,通过super.h.invoke调用代理类JDKProxy中的invoke方法来完成的,该invoke方法时通过反射机制调用目标类的原始方法。

2.CGLIB代理源码分析

2.1创建代理对象

由第一步的3.1场景,创建代理对象执行的是enhancer.create()方法,看下执行的源码,如下,

public Object create() {
    this.classOnly = false;
    this.argumentTypes = null;
    return this.createHelper();
}
private Object createHelper() {
    // 校验callbackTypes、filter是否为空,以及为空时的处理
    this.preValidate();
    // 通过newInstance方法来创建EnhancerKey对象
    Object key = KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter == ALL_ZERO ? null : new WeakCacheKey(this.filter), this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID);
    // 设置当前enhancer的代理类的key标识
    this.currentKey = key;
    // 调用父类即AbstractClassGenerator的创建代理类
    Object result = super.create(key);
    return result;
}

然后执行的AbstractClassGenerator.java中的create方法,源码如下,

protected Object create(Object key) {
    try {
        // 获取到当前生成器的类加载器
        ClassLoader loader = this.getClassLoader();
        // 当前类加载器对应的缓存,缓存key为类加载器,缓存的value为ClassLoaderData
        Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> cache = CACHE;
        // 先从缓存中获取下当前类加载器所有加载过的类
        AbstractClassGenerator.ClassLoaderData data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
        // 如果为空
        if (data == null) {
            Class var5 = AbstractClassGenerator.class;
            synchronized(AbstractClassGenerator.class) {
                cache = CACHE;
                data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader);
                // 经典的防止并发修改 二次判断
                if (data == null) {
                    // 新建一个缓存Cache  并将之前的缓存Cache的数据添加进来 并将已经被gc回收的数据给清除掉
                    Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> newCache = new WeakHashMap(cache);
                    // 新建一个当前加载器对应的ClassLoaderData 并加到缓存中  但ClassLoaderData中此时还没有数据
                    data = new AbstractClassGenerator.ClassLoaderData(loader);
                    newCache.put(loader, data);
                    // 刷新全局缓存
                    CACHE = newCache;
                }
            }
        }
        // 设置一个全局key
        this.key = key;
        // 在刚创建的data(ClassLoaderData)中调用get方法 并将当前生成器,
        // 以及是否使用缓存的标识传进去,系统参数 System.getProperty("cglib.useCache", "true")  
        // 返回的是生成好的代理类的class信息
        Object obj = data.get(this, this.getUseCache());
        // 如果为class则实例化class并返回,就是我们需要的代理类对象
        // 如果不是则说明是实体  则直接执行另一个方法返回实体对象
        return obj instanceof Class ? this.firstInstance((Class)obj) : this.nextInstance(obj);
    } catch (RuntimeException var9) {
        throw var9;
    } catch (Error var10) {
        throw var10;
    } catch (Exception var11) {
        throw new CodeGenerationException(var11);
    }
}

这个方法可以看到主要为根据类加载器定义一个缓存,里面装载了缓存的类信息,然后调用这个ClassLoaderData的get方法获取到数据,如果为class信息 那么直接使用反射实例化,如果返回的是实体类,则解析实体类的信息,调用其newInstance方法重新生成一个实例(cglib的代理类都会生成newInstance方法)。

重点看下data.get(this, this.getUseCache())方法实现,

public Object get(AbstractClassGenerator gen, boolean useCache) {
    // 如果不用缓存  (默认使用)
    if (!useCache) {
        // 则直接调用生成器的命令
        return gen.generate(this);
    } else {
        // 从缓存中获取值
        Object cachedValue = this.generatedClasses.get(gen);
        // 解包装并返回
        return gen.unwrapCachedValue(cachedValue);
    }
}

我们重点看如何生成代理类,gen.generate方法最终调用AbstractClassGenerator的generate方法,如下,

protected Class generate(ClassLoaderData data) {
    this.validate();
    if (this.superclass != null) {
        this.setNamePrefix(this.superclass.getName());
    } else if (this.interfaces != null) {
        this.setNamePrefix(this.interfaces[ReflectUtils.findPackageProtected(this.interfaces)].getName());
    }
​
    return super.generate(data);
}
protected Class generate(AbstractClassGenerator.ClassLoaderData data) {
    Object save = CURRENT.get();
    // 当前的代理类生成器存入ThreadLocal中
    CURRENT.set(this);
​
    try {
        // 获取到ClassLoader
        ClassLoader classLoader = data.getClassLoader();
        // 判断不能为空
        if (classLoader == null) {
            throw new IllegalStateException("ClassLoader is null while trying to define class " + this.getClassName() + ". It seems that the loader has been expired from a weak reference somehow. Please file an issue at cglib's issue tracker.");
        } else {
            String className;
            synchronized(classLoader) {
                // 生成代理类名字
                className = this.generateClassName(data.getUniqueNamePredicate());
                // 缓存中存入这个名字
                data.reserveName(className);
                // 当前代理类生成器设置类名
                this.setClassName(className);
            }
​
            Class gen;
            // 尝试从缓存中获取类
            if (this.attemptLoad) {
                try {
                    // 要是能获取到就直接返回了,即可能出现并发 其他线程已经加载
                    gen = classLoader.loadClass(this.getClassName());
                    Class var25 = gen;
                    return var25;
                } catch (ClassNotFoundException var20) {
                }
            }
            // 生成字节码
            byte[] b = this.strategy.generate(this);
            // 获取到字节码代表的class的名字
            className = ClassNameReader.getClassName(new ClassReader(b));
            // 核实是否为protect
            ProtectionDomain protectionDomain = this.getProtectionDomain();
            synchronized(classLoader) {
                // 如果不是protect
                if (protectionDomain == null) {
                    // 根据字节码、类加载器以及类名字,将class加载到内存中
                    gen = ReflectUtils.defineClass(className, b, classLoader);
                } else {
                    // 根据字节码、类加载器以及类名字,以及找到的Protect级别的实体,将class加载到内存中
                    gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
                }
            }
            // 返回生成的class信息
            Class var8 = gen;
            return var8;
        }
    } catch (RuntimeException var21) {
        throw var21;
    } catch (Error var22) {
        throw var22;
    } catch (Exception var23) {
        throw new CodeGenerationException(var23);
    } finally {
        CURRENT.set(save);
    }
}

这个方法主要设置了下当前类生成器的类名,然后调用stratege的generate方法返回字节码,根据字节码 类名 类加载器将字节码所代表的类加载到内存中,这个功能看一下大概就懂,我们接下来主要分析字节码生成方法。

public byte[] generate(ClassGenerator cg) throws Exception {
    // 创建一个写入器
    DebuggingClassWriter cw = this.getClassVisitor();
    // 加入自己的转换逻辑后执行代理类生成器的generateClass方法
    this.transform(cg).generateClass(cw);
    // 将cw写入的东西转换为byte数组返回
    return this.transform(cw.toByteArray());
}

上面的generateClass调用的是Enhancer的generateClass方法,源码如下,

public void generateClass(ClassVisitor v) throws Exception {
    // 声明需代理的类 或者接口
    Class sc = this.superclass == null ? Object.class : this.superclass;
    // 检查 final类无法被继承
    if (TypeUtils.isFinal(sc.getModifiers())) {
        throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
    } else {
        // 找到该类所有声明了的构造函数
        List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
        // 去掉private之类的不能被继承的构造函数
        this.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();
        // 声明所有必须为public的方法集合,这儿主要是代理接口接口的方法
        final Set forcePublic = new HashSet();
        // 即通过传入的代理类,代理接口,遍历所有的方法并放入对应的集合
        getMethods(sc, this.interfaces, actualMethods, interfaceMethods, forcePublic);
        // 对所有代理类方法修饰符做处理
        List methods = CollectionUtils.transform(actualMethods, new Transformer() {
            public Object transform(Object value) {
                Method method = (Method)value;
                int modifiers = 16 | method.getModifiers() & -1025 & -257 & -33;
                if (forcePublic.contains(MethodWrapper.create(method))) {
                    modifiers = modifiers & -5 | 1;
                }
​
                return ReflectUtils.getMethodInfo(method, modifiers);
            }
        });
        // 创建类写入器
        ClassEmitter e = new ClassEmitter(v);
        // 1.开始创建类  并写入基本信息  如java版本,类修饰符 类名等
        if (this.currentData == null) {
            e.begin_class(52, 1, this.getClassName(), Type.getType(sc), this.useFactory ? TypeUtils.add(TypeUtils.getTypes(this.interfaces), FACTORY) : TypeUtils.getTypes(this.interfaces), "<generated>");
        } else {
            e.begin_class(52, 1, this.getClassName(), (Type)null, new Type[]{FACTORY}, "<generated>");
        }
​
        List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
        // 2. 声明一个private boolean 类型的属性:CGLIB$BOUND
        e.declare_field(2, "CGLIB$BOUND", Type.BOOLEAN_TYPE, (Object)null);
        // 3. 声明一个public static Object 类型的属性:CGLIB$FACTORY_DATA
        e.declare_field(9, "CGLIB$FACTORY_DATA", OBJECT_TYPE, (Object)null);
        //  这个默认为true  如果为false则会声明一个private boolean 类型的属性:CGLIB$CONSTRUCTED
        if (!this.interceptDuringConstruction) {
            e.declare_field(2, "CGLIB$CONSTRUCTED", Type.BOOLEAN_TYPE, (Object)null);
        }
        // 4. 声明一个public static final 的ThreadLocal:ThreadLocal
        e.declare_field(26, "CGLIB$THREAD_CALLBACKS", THREAD_LOCAL, (Object)null);
        // 5. 声明一个public static final 的CallBack类型的数组:CGLIB$STATIC_CALLBACKS
        e.declare_field(26, "CGLIB$STATIC_CALLBACKS", CALLBACK_ARRAY, (Object)null);
        // 如果serialVersionUID不为null  则设置一个public static final 的Long类型 serialVersionUID
        if (this.serialVersionUID != null) {
            e.declare_field(26, "serialVersionUID", Type.LONG_TYPE, this.serialVersionUID);
        }
        // 遍历CallBackTypes 即我们构建Enhancer是setCallBack的所有类的类型  本案例中是methodInterceptor 并且只传入了一个
        for(int i = 0; i < this.callbackTypes.length; ++i) {
            // 6.声明一个private 的传入的CallBack类型的属性:CGLIB$CALLBACK_0 (从0开始编号,)
            e.declare_field(2, getCallbackField(i), this.callbackTypes[i], (Object)null);
        }
        // 7声明一个private static 的传入的Object类型的属性:CGLIB$CALLBACK_FILTER
        e.declare_field(10, "CGLIB$CALLBACK_FILTER", OBJECT_TYPE, (Object)null);
        // 判断currentData
        if (this.currentData == null) {
            // 8.为null则开始声明所有的代理类方法的变量 以及其具体的重写实现方法,还有static初始化执行代码块
            this.emitMethods(e, methods, actualMethods);
            // 9.声明构造函数
            this.emitConstructors(e, constructorInfo);
        } else {
            // 声明默认构造函数
            this.emitDefaultConstructor(e);
        }
​
        this.emitSetThreadCallbacks(e);
        this.emitSetStaticCallbacks(e);
        this.emitBindCallbacks(e);
        // 如果currentData不为null
        if (this.useFactory || this.currentData != null) {
            // 获取到所有CallBack索引数组
            int[] keys = this.getCallbackKeys();
            // 10.声明三个newInstance方法
            // 只有一个callback参数
            this.emitNewInstanceCallbacks(e);
            // 参数为callback数组
            this.emitNewInstanceCallback(e);
            // 参数为callback数组 以及附带的一些参数
            this.emitNewInstanceMultiarg(e, constructorInfo);
            // 11.声明getCallBack方法
            this.emitGetCallback(e, keys);
            // 12.声明setCallBack方法
            this.emitSetCallback(e, keys);
            // 13.声明getCallBack方法
            this.emitGetCallbacks(e);
            // 14.声明setCallBacks方法
            this.emitSetCallbacks(e);
        }
        // 类声明结束
        e.end_class();
    }
}

DebuggingClassWriter中toByteArray方法源码如下,

public byte[] toByteArray() {
    return (byte[])((byte[])AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            byte[] b = ((ClassWriter)DebuggingClassWriter.access$001(DebuggingClassWriter.this)).toByteArray();
            if (DebuggingClassWriter.debugLocation != null) {
                String dirs = DebuggingClassWriter.this.className.replace('.', File.separatorChar);
​
                try {
                    (new File(DebuggingClassWriter.debugLocation + File.separatorChar + dirs)).getParentFile().mkdirs();
                    File file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".class");
                    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
​
                    try {
                        out.write(b);
                    } finally {
                        out.close();
                    }
                    // 使用asm技术生成class文件
                    if (DebuggingClassWriter.traceCtor != null) {
                        file = new File(new File(DebuggingClassWriter.debugLocation), dirs + ".asm");
                        out = new BufferedOutputStream(new FileOutputStream(file));
​
                        try {
                            ClassReader cr = new ClassReader(b);
                            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
                            ClassVisitor tcv = (ClassVisitor)DebuggingClassWriter.traceCtor.newInstance(null, pw);
                            cr.accept(tcv, 0);
                            pw.flush();
                        } finally {
                            out.close();
                        }
                    }
                } catch (Exception var17) {
                    throw new CodeGenerationException(var17);
                }
            }
​
            return b;
        }
    }));
}
static {
    if (debugLocation != null) {
        System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
​
        try {
            Class clazz = Class.forName("org.objectweb.asm.util.TraceClassVisitor");
            traceCtor = clazz.getConstructor(ClassVisitor.class, PrintWriter.class);
        } catch (Throwable var1) {
        }
    }
​
}

最后,执行主程序里的firstInstance,最后会调用ReflectUtils.newInstance来实例化代理类对象,然后返回该代理类对象。

至此,CGLIB创建代理类创建流程结束,整个过程实现更复杂,生成代理类相比JDK动态代理效率低。

2.2调用代理对象

由第一步的3.1场景生成的代理类class文件可以看出,执行的是class文件中的sayHello方法,

public final void sayHello() {
    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$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
    } else {
        super.sayHello();
    }
}

var10000获取到的就是CGLibProxy对象,所以最终会调用CGLibProxy的intercept方法,该方法里,我们用了method.invoke通过反射机制调用了目标类的原始方法。

2.3类MethodProxy中invoke和invokeSuper执行源码分析及区别

在网上或者实际使用中,会经常看到在代理的拦截方法intercept中会通过methodProxy.invokeSuper来执行目标类的原始方法,使用它的作用是什么?以及相比于method.invoke有哪些优势?不着急,我们先根据源码搞懂它的原理。

首先,我们通过实际的例子,先看下使用methodProxy.invokeSuper会生成那些代理class文件。修改CGLibProxy的intercept方法,如下,

@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    // 检查权限
    checkPopedom();
    Object obj = null;
    try {
        // 前置通知
        before();
        // obj = methodProxy.invoke(proxy, args);
        obj = methodProxy.invokeSuper(proxy, args);
        // 后置通知
        after();
    } catch (Exception e) {
        // 异常通知
        exception();
    } finally {
        // 方法返回前通知
        beforeReturning();
    }
    return obj;
}

然后执行如下代码,

package com.test.proxy;
​
import net.sf.cglib.core.DebuggingClassWriter;
​
public class ProxyPerformanceTest {
​
    public static void main(String[] args) {
        // 该方法是为了生成由CGLIB生成的代理对象CLASS文件
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
        System.out.println("-----------CGLibProxy not use interface start-------------");
        HelloWorld helloWorldCglib = (HelloWorld) new CGLibProxy().createProxy(new HelloWorld());
        helloWorldCglib.sayHello();
        System.out.println("-----------CGLibProxy not use interface end-------------");
    }
}

执行结果如下,

-----------CGLibProxy not use interface start-------------
CGLIB debugging enabled, writing to 'D:\class'
CGLibProxy:检查权限  checkPopedom()!
CGLibProxy:before method invoke...
say HelloWorld
CGLibProxy:after method invoke...
CGLibProxy:beforeReturning method invoke...
-----------CGLibProxy not use interface end-------------

并生成如下三个class文件:

HelloWorld$$EnhancerByCGLIB$$74b9b49$$FastClassByCGLIB$$40d2459c.class
HelloWorld$$EnhancerByCGLIB$$74b9b49.class
HelloWorld$$FastClassByCGLIB$$212e5eaf.class

在这里,先提前说明下这三个文件是什么,

HelloWorld$$EnhancerByCGLIB$$74b9b49.class是实际生成的代理类;

HelloWorld$$FastClassByCGLIB$$212e5eaf.class是被代理类HelloWorld的FastClass;

HelloWorld$$EnhancerByCGLIB$$74b9b49$$FastClassByCGLIB$$40d2459c.class是代理类HelloWorld$$EnhancerByCGLIB$$74b9b49.class的FastClass。

注意,Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class(就是上面的两个FastClass的class文件),这个Class会为代理类或被代理类的方法分配一个index(int类型)。 这个index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比JDK动态代理通过反射调用高。

这么说可能比较难以理解,我们来看下代理类执行的过程就知道了。

FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy的invoke/invokeSuper时生成的并放在了缓存中。

执行MethodProxy的invoke/invokeSuper前首先调用MethodProxy的init()方法创建FastClass文件,如下,

private void init() {
    if (this.fastClassInfo == null) {
        synchronized(this.initLock) {
            if (this.fastClassInfo == null) {
                MethodProxy.CreateInfo ci = this.createInfo;
                MethodProxy.FastClassInfo fci = new MethodProxy.FastClassInfo();
                // 如果缓存中有就取出,没有就生成新的FastClass
                fci.f1 = helper(ci, ci.c1);
                fci.f2 = helper(ci, ci.c2);
                // 获取方法的index
                fci.i1 = fci.f1.getIndex(this.sig1);
                fci.i2 = fci.f2.getIndex(this.sig2);
                this.fastClassInfo = fci;
                this.createInfo = null;
            }
        }
    }
​
}
private static class FastClassInfo {
    // 被代理类FastClass
    FastClass f1;
    // 代理类FastClass
    FastClass f2;
    // 被代理类的方法签名(index)
    int i1;
    // 代理类的方法签名
    int i2;
​
    private FastClassInfo() {
    }
}

invoke和invokeSuper方法源码如下,

public Object invoke(Object obj, Object[] args) throws Throwable {
    try {
        this.init();
        MethodProxy.FastClassInfo fci = this.fastClassInfo;
        // 调用被代理类FastClass的invoke
        return fci.f1.invoke(fci.i1, obj, args);
    } catch (InvocationTargetException var4) {
        throw var4.getTargetException();
    } catch (IllegalArgumentException var5) {
        if (this.fastClassInfo.i1 < 0) {
            throw new IllegalArgumentException("Protected method: " + this.sig1);
        } else {
            throw var5;
        }
    }
}
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        this.init();
        MethodProxy.FastClassInfo fci = this.fastClassInfo;
        // 调用代理类FastClass的invoke
        return fci.f2.invoke(fci.i2, obj, args);
    } catch (InvocationTargetException var4) {
        throw var4.getTargetException();
    }
}

invoke和invokeSuper方法都会调用各自FastClass的invoke方法,有什么区别呢,上面可以debug看下f1,f2,i1,i2返回的结果,再来看下生成的两个FastClass,如下:

被代理类FastClass的class文件文件内容如下,

package com.test.proxy;
​
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.reflect.FastClass;
​
public class HelloWorld$$FastClassByCGLIB$$212e5eaf extends FastClass {
    public HelloWorld$$FastClassByCGLIB$$212e5eaf(Class var1) {
        super(var1);
    }
​
    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case 1535311470:
            if (var10000.equals("sayHello()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 -2012993625:
            if (var1.equals("sayHello")) {
                switch(var2.length) {
                case 0:
                    return 0;
                }
            }
            break;
        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 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 {
        HelloWorld var10000 = (HelloWorld)var2;
        int var10001 = var1;
​
        try {
            switch(var10001) {
            case 0:
                var10000.sayHello();
                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 {
        HelloWorld var10000 = new HelloWorld;
        HelloWorld 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;
    }
}

因为fci.f1.getIndex(this.sig1)获取到的index为0,所以如果CGLibProxy中的intercept中执行MethodProxy的invoke方法时,根据刚才的index为0,实际调用的是var10000.sayHello(),然后调用代理类中的sayHello(),然后调用的CGLibProxy中的intercept,然后再执行其中的MethodProxy的invoke方法,这样形成了一个死循环。所以说,在CGLibProxy中的intercept中执行MethodProxy的invoke方法,会形成死循环,应避免使用MethodProxy的invoke方法。

代理类FastClass的class文件文件内容如下,

package com.test.proxy;
​
import com.test.proxy.HelloWorld..EnhancerByCGLIB..74b9b49;
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.reflect.FastClass;
​
public class HelloWorld$$EnhancerByCGLIB$$74b9b49$$FastClassByCGLIB$$40d2459c extends FastClass {
    public HelloWorld$$EnhancerByCGLIB$$74b9b49$$FastClassByCGLIB$$40d2459c(Class var1) {
        super(var1);
    }
​
    public int getIndex(Signature var1) {
        String var10000 = var1.toString();
        switch(var10000.hashCode()) {
        case -2055565910:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1882565338:
            if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
                return 20;
            }
            break;
        case -1457535688:
            if (var10000.equals("CGLIB$STATICHOOK1()V")) {
                return 10;
            }
            break;
        case -1411842725:
            if (var10000.equals("CGLIB$hashCode$3()I")) {
                return 17;
            }
            break;
        case -894172689:
            if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 4;
            }
            break;
        case -623122092:
            if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
                return 15;
            }
            break;
        case -508378822:
            if (var10000.equals("clone()Ljava/lang/Object;")) {
                return 3;
            }
            break;
        case -419626537:
            if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 7;
            }
            break;
        case 291273791:
            if (var10000.equals("CGLIB$sayHello$0()V")) {
                return 19;
            }
            break;
        case 560567118:
            if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
                return 9;
            }
            break;
        case 811063227:
            if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 5;
            }
            break;
        case 973717575:
            if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
                return 14;
            }
            break;
        case 1221173700:
            if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                return 6;
            }
            break;
        case 1230699260:
            if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
                return 13;
            }
            break;
        case 1306468936:
            if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
                return 16;
            }
            break;
        case 1535311470:
            if (var10000.equals("sayHello()V")) {
                return 8;
            }
            break;
        case 1584330438:
            if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 12;
            }
            break;
        case 1800494055:
            if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
                return 18;
            }
            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 -2012993625:
            if (var1.equals("sayHello")) {
                switch(var2.length) {
                case 0:
                    return 8;
                }
            }
            break;
        case -1983192202:
            if (var1.equals("CGLIB$sayHello$0")) {
                switch(var2.length) {
                case 0:
                    return 19;
                }
            }
            break;
        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 14;
                }
            }
            break;
        case -124978609:
            if (var1.equals("CGLIB$equals$1")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("java.lang.Object")) {
                        return 20;
                    }
                }
            }
            break;
        case -60403779:
            if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 12;
                    }
                }
            }
            break;
        case -29025555:
            if (var1.equals("CGLIB$hashCode$3")) {
                switch(var2.length) {
                case 0:
                    return 17;
                }
            }
            break;
        case 85179481:
            if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 11;
                    }
                }
            }
            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 10;
                }
            }
            break;
        case 495524492:
            if (var1.equals("setCallbacks")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                        return 7;
                    }
                }
            }
            break;
        case 1154623345:
            if (var1.equals("CGLIB$findMethodProxy")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {
                        return 15;
                    }
                }
            }
            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 -845341380:
                        if (var10001.equals("net.sf.cglib.proxy.Callback")) {
                            return 4;
                        }
                        break;
                    case 1730110032:
                        if (var10001.equals("[Lnet.sf.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("[Lnet.sf.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("net.sf.cglib.proxy.Callback")) {
                        return 9;
                    }
                }
            }
            break;
        case 1905679803:
            if (var1.equals("getCallback")) {
                switch(var2.length) {
                case 1:
                    if (var2[0].getName().equals("int")) {
                        return 13;
                    }
                }
            }
            break;
        case 1951977610:
            if (var1.equals("CGLIB$clone$4")) {
                switch(var2.length) {
                case 0:
                    return 18;
                }
            }
        }
​
        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 {
        74b9b49 var10000 = (74b9b49)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.setCallbacks((Callback[])var3[0]);
                return null;
            case 8:
                var10000.sayHello();
                return null;
            case 9:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            case 10:
                74b9b49.CGLIB$STATICHOOK1();
                return null;
            case 11:
                74b9b49.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
                return null;
            case 12:
                74b9b49.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
                return null;
            case 13:
                return var10000.getCallback(((Number)var3[0]).intValue());
            case 14:
                return var10000.getCallbacks();
            case 15:
                return 74b9b49.CGLIB$findMethodProxy((Signature)var3[0]);
            case 16:
                return var10000.CGLIB$toString$2();
            case 17:
                return new Integer(var10000.CGLIB$hashCode$3());
            case 18:
                return var10000.CGLIB$clone$4();
            case 19:
                var10000.CGLIB$sayHello$0();
                return null;
            case 20:
                return new Boolean(var10000.CGLIB$equals$1(var3[0]));
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }
​
        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
​
    public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
        74b9b49 var10000 = new 74b9b49;
        74b9b49 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;
    }
}

因为fci.f2.getIndex(this.sig2)获取到的index为19,所以如果CGLibProxy中的intercept中执行MethodProxy的invokeSuper方法时,根据刚才的index为19,实际调用的是var10000.CGLIB$sayHello$0();,然后调用代理类中的CGLIB$sayHello$0(),然后调用的super.sayHello(),也就是调用被代理类HelloWorld的sayHello()方法。

再回看刚才的问题,在网上或者实际使用中,会经常看到在代理的拦截方法intercept中会通过methodProxy.invokeSuper来执行目标类的原始方法,使用它的作用是什么?以及相比于method.invoke有哪些优势?

很明显,invoke和invokeSuper的作用都是是为了创建代理类和被代理类的各自Fastclass类,Fastclass类是个class文件,里面主要是使用索引号index的方式,用index查找到相应的代理方法,实际的代理方法在代理类中。生成Fastclass只在第一次调用invoke或invokeSuper时生成,之后就用已生成的Fastclass就可以了。

invokeSuper通过索引号index调用的是被代理类(如上例中的HelloWorld.java)的目标方法。

invoke通过索引号index调用的是代理实现(CGLibProxy)中的拦截器,会在成死循环,报错:java.lang.StackOverflowError。这个问题怎么解决呢?解决办法就是在methodProxy.invoke方法的第一个参数传入被代理对象即可,具体如下例,修改CGLibProxy中的intercept方法,

@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    // 检查权限
    checkPopedom();
    Object obj = null;
    try {
        // 前置通知
        before();
        obj = methodProxy.invoke(targetObject, args);
        // 后置通知
        after();
    } catch (Exception e) {
        // 异常通知
        exception();
    } finally {
        // 方法返回前通知
        beforeReturning();
    }
    return obj;
}

这块的原理就是,之前传代理对象proxy,在Fastclass中会调用代理类的拦截器,或造成死循环。如果传入targetObject之后,那么Fastclass中在调用var10000.sayHello()时,var10000就是targetObject,所以最终直接调用被代理对象的目标方法,而不会再到代理类中。在spring aop中就是这么用的。

使用cglib的invokeSuper要比jdk代理的method.invoke,从原理上要快得多。

三、总结

1.对于CGLIB代理,无论类是否实现接口,都可以代理,通过继承目标对象来生成代理对象,并重写目标对象的所有方法。所以CGLIB不能代理由final修饰的类或者方法。CGLIB代理是通过ASM开源包,对目标对象类的class文件加载进来,通过修改其字节码生成子类来处理。核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。

2.对于JDK动态代理,因为其默认必须继承Proxy类,但是java不支持多继承,所以JDK代理只能代理接口实现类。JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。

3.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。

4.JDK调用代理方法,是通过反射机制调用,Cglib可以通过FastClass机制直接调用方法,Cglib执行效率更高。

扩展:

Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。

SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB。

在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxyTargetClass配置已无效。

参考资料:

https:// blog.csdn.net/u013419838/article/details/93749164

https:// blog.csdn.net/u013277209/article/details/114707651

https:// blog.csdn.net/zhanghongzheng3213/article/details/81238900


版权声明:本文为u013521882原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。