动态代理详解

代理的本质是非侵入式地对被代理对象方法的增强,即在原有方法上加日志等内容

一、静态代理

1、静态代理实现

接口:

public interface SampleInterface {
    void test();
}

被代理类:

public class Sample implements SampleInterface {
    @Override
    public void test() {
        System.out.println("Test");
    }
}

 代理类:

public class Proxy implements SampleInterface {
    private SampleInterface sampleInterface = new Sample();
    
    @Override
    public void test() {
        System.out.println("Before Test");
        sampleInterface.test();
        System.out.println("After Test");
    }
}

代理类调用:

被代理类被传递给了代理类Proxy,代理类在执行具体方法时通过所持用的被代理类完成调用

public static void main(String[] args) {
    Proxy proxy = new Proxy();
    proxy.test();
}
   

使用静态代理很容易就完成了对一个类的代理操作。但是静态代理的缺点也暴露了出来:由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐

讲述动态代理实现之前,我们要知道扩展一个类有常见的两种方式:

  • 实现接口(JDK动态代理)
  • 继承父类(CGLIB动态代理)

二、JDK动态代理

调用处理器接口(InvocationHandler)实现类注入被代理对象, 通过反射机制自动生成代理对象,代理对象调用方法(被invoke方法拦截,在invoke方法中进行增强操作,比如加日志等)

实现JDK动态代理主要用到了反射的两个API

  • java.lang.reflect.Proxy
  • java.lang.reflect.InvocationHandler

InvocationHandler接口有一个invoke方法,这是所有代理对象调用方法的入口

1、动态代理实现

接口:

public interface SampleInterface {
    void test();
}

被代理类:

public class Sample implements SampleInterface {
    @Override
    public void test() {
        System.out.println("Test");
    }
}

实现调用处理器接口(InvocationHandler):

class ProxyFactory implements InvocationHandler {
    //被代理对象
    private Object object;

    public void ProxyFactory(Object object) {
        //注入被代理对象
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //增强操作
        System.out.println("Before Test");
        
        //方法的正常调用
        Object result = method.invoke(object, args);
        
        //增强操作
        System.out.println("After Test");

        return result;
    }
}

执行动态代理:

public static void main(String[] args) {
    //生成$Proxy0 
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

    //创建被代理对象
    SampleInterface sample = new Sample();
    
    //创建调用处理器对象
    InvocationHandler handler = new ProxyFactory(test);

    //生成代理对象
    SampleInterface proxy = (SampleInterface) Proxy.newProxyInstance(sample.getClass().getClassLoader(), sample.getClass().getInterfaces(), handler);
    
    //通过代理对象调用方法,实际上会转到invoke方法调用
    proxy.test();
}

2、Proxy类的newProxyInstance方法解析

public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    /** 代理类构造器的参数类型 */
    private static final Class<?>[] constructorParams =
        { InvocationHandler.class };

    /**
     * 代理类的缓存
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    /**
     * 代理实例的调用处理器
     * @serial
     */
    protected InvocationHandler h;

    /**
     * 禁止实例化
     */
    private Proxy() {
    }

    /**
     * 构造一个新的实例
     */
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        /*
         * 判断调用处理器是否为空,为空直接抛空指针异常
         */
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * 查找或者生成代理类
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                /*
                 * 检查权限
                 */
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            /*
             * 获取参数类型为InvocationHandler.class的代理类构造器
             */
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            /*
             * 设置修饰符
             */
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            /*
             * 返回参数为h(InvocationHandler接口实现类)的代理实例$Proxy0
             */
            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);
        }
    }
}

3、$Proxy0解析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
 
package com.sun.proxy;
 
import com.konka.SampleInterface;
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 SampleInterface {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;
 
    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})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
 
    public final void test() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
 
    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)).intValue();
        } 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"));
            m3 = Class.forName("com.konka.SampleInterface").getMethod("test");
            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());
        }
    }
}

可以看到,Proxy类的newProxyInstance()方法被调用,该方法返回一个被代理对象的实例,然后向上转型为其对应的接口。问题是该方法在返回之前已经做了什么?我们看看其参数的第三个:handler,它就是InvocationHandler接口实现类(ProxyFactory)的一个实例。因为InvocationHandler接口中原本有个invoke()方法,所以其实现类当然需要实现这个方法,即其实现类(在此是ProxyFactory类)中有invoke()方法,而如果invoke()方法要被调用,只能通过ProxyFactory类对象来调用

而$Proxy0的代码中,有三个地方已经用ProxyFactory类对象来调用invoke()方法,他们分别在这些方法的代码中:public final boolean equals(Object obj) ;public final int hashCode() ;public final String toString()。也许你会有疑问,这个方法也没有看到在哪里被$Proxy0对象调用过,怎么能执行invoke方法呢?但是请看$Proxy0中的static代码块,这个模块是特殊的,因为当newProxyInstance方法创建$Proxy0时,它就被初始化。而这个static模块中的getMethod方法加载了这个三个方法,因而它们里面的代码(h.invoke())被执行

三、CGLIB动态代理

对于JDK动态代理,被代理类必须实现接口,也就是说它是面向接口的,而CGLIB动态代理则可以不实现接口

1、动态代理实现

引入依赖(cglib是第三方类库,需要引入依赖):

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>

被代理类(这里不再需要实现接口):

public class Sample {
    @Override
    public void test() {
        System.out.println("Test");
    }
}

实现方法拦截器接口(MethodInterceptor):

public class ProxyFactory implements MethodInterceptor {
    //被代理对象
    private Object object;

    public ProxyFactory(Object object) {
        //注入被代理对象
        this.object = object;
    }

    @Override
    public Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable {
        //增强操作
        System.out.println("Before Test");
        
        //方法的正常调用
        Object result = method.invoke(object, var3);
        
        //增强操作
        System.out.println("After Test");

        return result;
    }
}

intercept()方法的四个参数:

  • var1:需要增强的对象,即实现这个接口类的一个对象
  • var2:要被拦截的方法
  • var3:要被拦截方法的参数
  • var4:要触发父类方法的对象

执行动态代理:

public static void main(String[] args) {
    //代理类class文件存入本地磁盘方便反编译查看源码
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
    
    //通过CGLIB动态代理获取代理对象的过程
    Enhancer enhancer = new Enhancer();
    
    //指定父类
    enhancer.setSuperclass(Sample.class);
    
    //指定回调器
    enhancer.setCallback(new ProxyFactory());
    
    //创建代理对象
    Sample proxy = (Sample) enhancer.create();
    
    //通过代理对象调用方法
    proxy.test(); 
}

2、源码解析

 在上面的main方法中,通过enhancer.create()方法创建代理对象,create()方法的源码如下:

public Object create() {
    this.classOnly = false;
    this.argumentTypes = null;
    return this.createHelper();
}

核心内容在createHelper()方法中,源码如下:

private Object createHelper() {
    //校验callbackTypes、filter是否为空以及为空时的处理
    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());
    }
    //CGLIB动态代理和JDK动态代理一样,运用了缓存功能
    //通过newInstance()方法创建EnhancerKey对象,作为Enhancer父类AbstractClassGenerator.create()方法创建代理对象的参数
    return super.create(KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter, this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID));
}

createHelper()方法执行父类AbstractClassGenerator的create()方法,源码如下:

protected Object create(Object key) {
    try {
        Class gen = null;
        synchronized(this.source) {
            ClassLoader loader = this.getClassLoader();
            Map cache2 = null;
            cache2 = (Map)this.source.cache.get(loader);
            if (cache2 == null) {
                cache2 = new HashMap();
                ((Map)cache2).put(NAME_KEY, new HashSet());
                this.source.cache.put(loader, cache2);
            } else if (this.useCache) {
                Reference ref = (Reference)((Map)cache2).get(key);
                gen = (Class)(ref == null ? null : ref.get());
            }
            if (gen == null) {
                Object save = CURRENT.get();
                CURRENT.set(this);
                Object var24;
                try {
                    this.key = key;
                    if (this.attemptLoad) {
                        try {
                            gen = loader.loadClass(this.getClassName());
                        } catch (ClassNotFoundException var17) {
                        }
                    }
                    if (gen == null) {
                        //根据策略生成字节码
                        //根据不同的ClassGenerator去生成不同的字节码,都是用ASM框架去生成字节码的
                        byte[] b = this.strategy.generate(this);
                        String className = ClassNameReader.getClassName(new ClassReader(b));
                        this.getClassNameCache(loader).add(className);
                        //生成代理类
                        gen = ReflectUtils.defineClass(className, b, loader);
                    }
                    if (this.useCache) {
                        ((Map)cache2).put(key, new WeakReference(gen));
                    }
                    //生成代理类对象
                    var24 = this.firstInstance(gen);
                } finally {
                    CURRENT.set(save);
                }
                return var24;
            }
        }
        return this.firstInstance(gen);
    } catch (RuntimeException var20) {
        throw var20;
    } catch (Error var21) {
        throw var21;
    } catch (Exception var22) {
        throw new CodeGenerationException(var22);
    }
}

根据firstInstance()方法可以找到最终生成代理类对象的方法是ReflectUtils类的nextInstance()方法,源码如下:

public static Object newInstance(Class type) {
    return newInstance(type, Constants.EMPTY_CLASS_ARRAY, (Object[])null);
}

public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
    return newInstance(getConstructor(type, parameterTypes), args);
}

public static Object newInstance(Constructor cstruct, Object[] args) {
    boolean flag = cstruct.isAccessible();
    Object var4;
    try {
        cstruct.setAccessible(true);
        Object result = cstruct.newInstance(args);
        var4 = result;
    } catch (InstantiationException var10) {
        throw new CodeGenerationException(var10);
    } catch (IllegalAccessException var11) {
        throw new CodeGenerationException(var11);
    } catch (InvocationTargetException var12) {
        throw new CodeGenerationException(var12.getTargetException());
    } finally {
        cstruct.setAccessible(flag);
    }
    return var4;
}

反编译代理类class文件,源码如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
 
package com.konka.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 Sample$$EnhancerByCGLIB$$be45efdd extends Sample 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$test$0$Method;
    private static final MethodProxy CGLIB$test$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.jpeony.spring.proxy.cglib.Sample$$EnhancerByCGLIB$$be45efdd");
        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$test$0$Method = ReflectUtils.findMethods(new String[]{"test", "()V"}, (var1 = Class.forName("com.jpeony.spring.proxy.cglib.Sample")).getDeclaredMethods())[0];
        CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$0");
    }
 
    final void CGLIB$test$0() {
        super.test();
    }
 
    public final void test() {
        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$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
        } else {
            super.test();
        }
    }
 
    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("test()V")) {
                return CGLIB$test$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 Sample$$EnhancerByCGLIB$$be45efdd() {
        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) {
        Sample$$EnhancerByCGLIB$$be45efdd var1 = (Sample$$EnhancerByCGLIB$$be45efdd)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);
        Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
 
    public Object newInstance(Callback var1) {
        CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
        Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd();
        CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
        return var10000;
    }
 
    public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
        CGLIB$SET_THREAD_CALLBACKS(var3);
        Sample$$EnhancerByCGLIB$$be45efdd var10000 = new Sample$$EnhancerByCGLIB$$be45efdd;
        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();
    }
}

可以看到代理对象继承于Sample,拦截器调用intercept()方法,intercept()方法由自定义ProxyFactory实现,所以,最后调用ProxyFactory中的intercept()方法

四、静态代理与动态代理的区别

1、静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件

2、动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中

五、JDK动态代理与CGLIB动态代理的区别

1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

2、Spring在选择用JDK还是CGLIB的依据:

  • 当Bean实现接口时,Spring就会用JDK的动态代理
  • 当Bean没有实现接口时,Spring使用CGLIB是实现
  • 可以强制使用CGLIB(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

3、CGLIB比JDK快?

  • 使用CGLIB实现动态代理,CGLIB底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLIB不能对声明为final的方法进行代理,因为CGLIB原理是动态生成被代理类的子类
  • 在对JDK动态代理与CGLIB动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGLIB要好20%左右
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

z.haoui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值