• 动态代理(CGlib和jdk)


    基础概念

    ● 什么是代理:

    顾名思义,代理就是帮别人做事情,比如代购,可能会收取一定的费用(代码中指对方法的增强)

    ● 什么是静态代理:

    静态代理是静态的,代理类由自己手动创建,在编译期就已经生成,并且代理的目标类是确定的,也就是由代码写死的,一旦运行就不能改变。

    ● 什么是动态代理

    与静态代理不同,动态代理的代理类运行期才生成,其代理的目标类也会根据传入的参数的改变而改变,也就是说,同一份代码,可以代理多个类(当然生成的代理类也不同),减少了代码的冗余

    静态代理

    //卖票接口
    public interface SellTickets {
        void sell();
    }
    
    //火车站  火车站具有卖票功能,所以需要实现SellTickets接口
    public class TrainStation implements SellTickets {
    
        public void sell() {
            System.out.println("火车站卖票");
        }
    }
    
    //代售点
    public class ProxyPoint implements SellTickets {
    
        private TrainStation station = new TrainStation();
    
        public void sell() {
            System.out.println("代理点收取一些服务费用");
            station.sell();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    上述代码就是一个简单的静态代理,其中ProxyPoint 就是代理类,可见其代理了TrainStation类,并对TrainStation类的sell方法进行增强(收取代理费用)

    不难看出,这份代码对于代理已经写死了,ProxyPoint 只能代理TrainStation类,如果要代理其他的类,需要重新建个代理类。可能会造成类爆炸。

    JDK 动态代理

    基于接口的动态代理

    jdk中提供了一个动态代理类,Proxy ,这个类 提供了一个 newProxyInstance 静态方法,可以帮助我们创建代理对象(代理类)。

    通过动态代理,因为代理对象是动态生成的,所有并不需要创建代理类,只需要一个代理工厂,通过工厂来动态生产代理类即可。

    newProxyInstance()方法参数说明:
    ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载器即可
    Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口
    InvocationHandler h : 代理对象的调用处理程序

    InvocationHandler中invoke方法参数说明:
    proxy : 代理对象
    method : 对应于在代理对象上调用的接口方法的 Method 实例
    args : 代理对象调用接口方法时传递的实际参数

    /**
    * 代理工厂,用来创建代理对象
    */
    public class ProxyFactory {
    
        private TrainStation train = new TrainStation();
        /**
         * 获取动态代理对象
         * @return
         */
        public SellTickets getProxyObject(){
    
            SellTickets proxyObject = (SellTickets) Proxy.newProxyInstance(train.getClass().getClassLoader(), train.getClass().getInterfaces(),
                    (proxy,method,args) -> {
                        System.out.println("方法增强,jdk动态代理模式");
                        Object res = method.invoke(train, args);
                        return res;
                    });
    
            return proxyObject;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    动态代理是在运行期生成代理对象,所以在代码层面是看不出代理对象的结构的。

    但可以借助java诊断工具 arthas-boot.jar ,获取运行时,内存中存在的代理类

    arthas 的简单使用

    首先程序保证一直运行,可以先打印出生成的代理对象的全类名
    在这里插入图片描述
    在这里插入图片描述

    启动 arthas

    java -jar arthas-boot.jar

    选择java进程

    在这里插入图片描述

    例:输入 1
    在这里插入图片描述

    反编译class文件

    jad 全类名
    在这里插入图片描述

    获取到 代理对象如下

    package com.sun.proxy;
    
    import com.rwto.structure.proxy.OtherTicket;
    import com.rwto.structure.proxy.SellTickets;
    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 SellTickets,
    OtherTicket {
        private static Method m1;
        private static Method m2;
        private static Method m3;
        private static Method m0;
    
        public $Proxy0(InvocationHandler invocationHandler) {
            super(invocationHandler);
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m3 = Class.forName("com.rwto.structure.proxy.SellTickets").getMethod("sell", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
                return;
            }
            catch (NoSuchMethodException noSuchMethodException) {
                throw new NoSuchMethodError(noSuchMethodException.getMessage());
            }
            catch (ClassNotFoundException classNotFoundException) {
                throw new NoClassDefFoundError(classNotFoundException.getMessage());
            }
        }
    
        public final boolean equals(Object object) {
            try {
                return (Boolean)this.h.invoke(this, m1, new Object[]{object});
            }
            catch (Error | RuntimeException throwable) {
                throw throwable;
            }
            catch (Throwable throwable) {
                throw new UndeclaredThrowableException(throwable);
            }
        }
    
        public final String toString() {
            try {
                return (String)this.h.invoke(this, m2, null);
            }
            catch (Error | RuntimeException throwable) {
                throw throwable;
            }
            catch (Throwable throwable) {
                throw new UndeclaredThrowableException(throwable);
            }
        }
    
        public final int hashCode() {
            try {
                return (Integer)this.h.invoke(this, m0, null);
            }
            catch (Error | RuntimeException throwable) {
                throw throwable;
            }
            catch (Throwable throwable) {
                throw new UndeclaredThrowableException(throwable);
            }
        }
    
    
        public final void sell() {
            try {
                this.h.invoke(this, m3, null);
                return;
            }
            catch (Error | RuntimeException throwable) {
                throw throwable;
            }
            catch (Throwable throwable) {
                throw new UndeclaredThrowableException(throwable);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    从上面的类中,我们可以看到以下几个信息:

    ● 代理类($Proxy0)实现了SellTickets。也就是说真实类和代理类实现同样的接口。
    ● 代理类($Proxy0)将我们提供了的匿名内部类对象传递给了父类。

    jdk 动态代理的执行流程如下

    执行流程如下:

    1. 在测试类中通过代理对象调用sell()方法
    2. 根据多态的特性,执行的是代理类($Proxy0)中的sell()方法
    3. 代理类($Proxy0)中的sell()方法中又调用了InvocationHandler接口的子实现类对象的invoke方法
    4. invoke方法通过反射执行了真实对象所属类(TrainStation)中的sell()方法

    CGLIB 动态代理

    JDK 动态代理虽然方便,但有一个致命的局限性,那就是被代理的方法必须 在接口中有定义,也就是被代理对象必须实现了相应的接口

    对于这个局限性的补充,就出现了CGlib :基于父类的动态代理

    CGLIB是第三方提供的包,所以需要引入jar包的坐标:

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.1</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码如下

    public class ProxyFactory implements MethodInterceptor {
        
        public TrainStation getProxyObject(){
            // 创建Enhancer对象 类似于 Proxy类
            Enhancer enhancer = new Enhancer();
            // 设置父类的字节码对象 即需要代理的类
            enhancer.setSuperclass(TrainStation.class);
            //设置回调函数,增强方法
            enhancer.setCallback(this);
            // 生成代理对象
            TrainStation proxy = (TrainStation) enhancer.create();
            return proxy;
        }
        
        /**
        * 方法拦截(增强)
        * @param o 代理对象
        * @param method 真实对象的method实例
        * @param args 实际参数
        * @param methodProxy 代理对象中的方法的method实例
        * @return
        * @throws Throwable
        */
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("方法增强,CGlib动态代理模式");
            TrainStation result = (TrainStation) methodProxy.invokeSuper(o, args);
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    通过arthas 工具获取 代理类

    package com.rwto.structure.proxy.cglib;
    
    import com.rwto.structure.proxy.cglib.TrainStation;
    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 TrainStation$$EnhancerByCGLIB$$b7647434
    extends TrainStation
    implements Factory {
        private boolean CGLIB$BOUND;
        private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
        private static final Callback[] CGLIB$STATIC_CALLBACKS;
        private MethodInterceptor CGLIB$CALLBACK_0;
        private static final Method CGLIB$sell$0$Method;
        private static final MethodProxy CGLIB$sell$0$Proxy;
        private static final Object[] CGLIB$emptyArgs;
        private static final Method CGLIB$finalize$1$Method;
        private static final MethodProxy CGLIB$finalize$1$Proxy;
        private static final Method CGLIB$equals$2$Method;
        private static final MethodProxy CGLIB$equals$2$Proxy;
        private static final Method CGLIB$toString$3$Method;
        private static final MethodProxy CGLIB$toString$3$Proxy;
        private static final Method CGLIB$hashCode$4$Method;
        private static final MethodProxy CGLIB$hashCode$4$Proxy;
        private static final Method CGLIB$clone$5$Method;
        private static final MethodProxy CGLIB$clone$5$Proxy;
    
        static void CGLIB$STATICHOOK1() {
            CGLIB$THREAD_CALLBACKS = new ThreadLocal();
            CGLIB$emptyArgs = new Object[0];
            Class<?> clazz = Class.forName("com.rwto.structure.proxy.cglib.TrainStation$$EnhancerByCGLIB$$b7647434");
            Class<?> clazz2 = Class.forName("com.rwto.structure.proxy.cglib.TrainStation");
            CGLIB$sell$0$Method = ReflectUtils.findMethods(new String[]{"sell", "()V"}, clazz2.getDeclaredMethods())[0];
            CGLIB$sell$0$Proxy = MethodProxy.create(clazz2, clazz, "()V", "sell", "CGLIB$sell$0");
            clazz2 = Class.forName("java.lang.Object");
            Method[] methodArray = ReflectUtils.findMethods(new String[]{"finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, clazz2.getDeclaredMethods());
            CGLIB$finalize$1$Method = methodArray[0];
            CGLIB$finalize$1$Proxy = MethodProxy.create(clazz2, clazz, "()V", "finalize", "CGLIB$finalize$1");
            CGLIB$equals$2$Method = methodArray[1];
            CGLIB$equals$2$Proxy = MethodProxy.create(clazz2, clazz, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
            CGLIB$toString$3$Method = methodArray[2];
            CGLIB$toString$3$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
            CGLIB$hashCode$4$Method = methodArray[3];
            CGLIB$hashCode$4$Proxy = MethodProxy.create(clazz2, clazz, "()I", "hashCode", "CGLIB$hashCode$4");
            CGLIB$clone$5$Method = methodArray[4];
            CGLIB$clone$5$Proxy = MethodProxy.create(clazz2, clazz, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
        }
    
        final void CGLIB$sell$0() {
            super.sell();
        }
    
        public final void sell() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                Object object = methodInterceptor.intercept(this, CGLIB$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy);
                return;
            }
            super.sell();
        }
    
        final void CGLIB$finalize$1() throws Throwable {
            super.finalize();
        }
    
        protected final void finalize() throws Throwable {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                Object object = methodInterceptor.intercept(this, CGLIB$finalize$1$Method, CGLIB$emptyArgs, CGLIB$finalize$1$Proxy);
                return;
            }
            super.finalize();
        }
    
        final boolean CGLIB$equals$2(Object object) {
            return super.equals(object);
        }
    
        public final boolean equals(Object object) {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                Object object2 = methodInterceptor.intercept(this, CGLIB$equals$2$Method, new Object[]{object}, CGLIB$equals$2$Proxy);
                return object2 == null ? false : (Boolean)object2;
            }
            return super.equals(object);
        }
    
        final String CGLIB$toString$3() {
            return super.toString();
        }
    
        public final String toString() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                return (String)methodInterceptor.intercept(this, CGLIB$toString$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy);
            }
            return super.toString();
        }
    
        final int CGLIB$hashCode$4() {
            return super.hashCode();
        }
    
        public final int hashCode() {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                Object object = methodInterceptor.intercept(this, CGLIB$hashCode$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
                return object == null ? 0 : ((Number)object).intValue();
            }
            return super.hashCode();
        }
    
        final Object CGLIB$clone$5() throws CloneNotSupportedException {
            return super.clone();
        }
    
        protected final Object clone() throws CloneNotSupportedException {
            MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
            if (methodInterceptor == null) {
                TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
                methodInterceptor = this.CGLIB$CALLBACK_0;
            }
            if (methodInterceptor != null) {
                return methodInterceptor.intercept(this, CGLIB$clone$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy);
            }
            return super.clone();
        }
    
        public static MethodProxy CGLIB$findMethodProxy(Signature signature) {
            String string = ((Object)signature).toString();
            switch (string.hashCode()) {
                case -1574182249: {
                    if (!string.equals("finalize()V")) break;
                    return CGLIB$finalize$1$Proxy;
                }
                case -508378822: {
                    if (!string.equals("clone()Ljava/lang/Object;")) break;
                    return CGLIB$clone$5$Proxy;
                }
                case 1826985398: {
                    if (!string.equals("equals(Ljava/lang/Object;)Z")) break;
                    return CGLIB$equals$2$Proxy;
                }
                case 1913648695: {
                    if (!string.equals("toString()Ljava/lang/String;")) break;
                    return CGLIB$toString$3$Proxy;
                }
                case 1978249955: {
                    if (!string.equals("sell()V")) break;
                    return CGLIB$sell$0$Proxy;
                }
                case 1984935277: {
                    if (!string.equals("hashCode()I")) break;
                    return CGLIB$hashCode$4$Proxy;
                }
            }
            return null;
        }
    
        public TrainStation$$EnhancerByCGLIB$$b7647434() {
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = this;
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(trainStation$$EnhancerByCGLIB$$b7647434);
        }
    
        public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] callbackArray) {
            CGLIB$THREAD_CALLBACKS.set(callbackArray);
        }
    
        public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] callbackArray) {
            CGLIB$STATIC_CALLBACKS = callbackArray;
        }
    
        private static final void CGLIB$BIND_CALLBACKS(Object object) {
            block2: {
                Object object2;
                block3: {
                    TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = (TrainStation$$EnhancerByCGLIB$$b7647434)object;
                    if (trainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BOUND) break block2;
                    trainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BOUND = true;
                    object2 = CGLIB$THREAD_CALLBACKS.get();
                    if (object2 != null) break block3;
                    object2 = CGLIB$STATIC_CALLBACKS;
                    if (CGLIB$STATIC_CALLBACKS == null) break block2;
                }
                trainStation$$EnhancerByCGLIB$$b7647434.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])object2)[0];
            }
        }
    
        public Object newInstance(Callback[] callbackArray) {
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = new TrainStation$$EnhancerByCGLIB$$b7647434();
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(null);
            return trainStation$$EnhancerByCGLIB$$b7647434;
        }
    
        public Object newInstance(Callback callback) {
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = new TrainStation$$EnhancerByCGLIB$$b7647434();
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(null);
            return trainStation$$EnhancerByCGLIB$$b7647434;
        }
    
        public Object newInstance(Class[] classArray, Object[] objectArray, Callback[] callbackArray) {
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434;
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
            Class[] classArray2 = classArray;
            switch (classArray.length) {
                case 0: {
                    trainStation$$EnhancerByCGLIB$$b7647434 = new TrainStation$$EnhancerByCGLIB$$b7647434();
                    break;
                }
                default: {
                    throw new IllegalArgumentException("Constructor not found");
                }
            }
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$SET_THREAD_CALLBACKS(null);
            return trainStation$$EnhancerByCGLIB$$b7647434;
        }
    
        public Callback getCallback(int n) {
            MethodInterceptor methodInterceptor;
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
            switch (n) {
                case 0: {
                    methodInterceptor = this.CGLIB$CALLBACK_0;
                    break;
                }
                default: {
                    methodInterceptor = null;
                }
            }
            return methodInterceptor;
        }
    
        public void setCallback(int n, Callback callback) {
            switch (n) {
                case 0: {
                    this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;
                    break;
                }
            }
        }
    
        public Callback[] getCallbacks() {
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$BIND_CALLBACKS(this);
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = this;
            return new Callback[]{this.CGLIB$CALLBACK_0};
        }
    
        public void setCallbacks(Callback[] callbackArray) {
            Callback[] callbackArray2 = callbackArray;
            TrainStation$$EnhancerByCGLIB$$b7647434 trainStation$$EnhancerByCGLIB$$b7647434 = this;
            this.CGLIB$CALLBACK_0 = (MethodInterceptor)callbackArray[0];
        }
    
        static {
            TrainStation$$EnhancerByCGLIB$$b7647434.CGLIB$STATICHOOK1();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284

    可以看出
    ● CGlib是通过生成一个子类 来继承 被代理的类,实现的动态代理,因此cglib不能代理被final修饰的类

    jdk 和 CGlib的效率比较:

    ● 使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的类或者方法进行代理,因为CGLib原理是动态生成被代理类的子类。
    ● 在JDK1.6、JDK1.7、JDK1.8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLib代理效率,只有当进行大量调用的时候,JDK1.6和JDK1.7比CGLib代理效率低一点,但是到JDK1.8的时候,JDK代理效率高于CGLib代理。所以如果有接口使用JDK动态代理,如果没有接口使用CGLIB代理。

  • 相关阅读:
    两整数之和 ---- 位运算
    3.RabbitMQ工作模式介绍
    【网盘源码】百度云盘手动cookie获取,添加到扫码系统管理平台。
    【TCP/IP知识点总结】
    【计算机视觉(CV)】基于图像分类网络VGG实现中草药识别(一)
    滚雪球学Java(44):掌握Java编程的关键:深入解析System类
    远程端点管理和安全性
    关于unaipp生成的vue3项目开启微信云函数所遇到的问题
    公众号突破公司注册数量限制
    人工智能时代大模型算法之文心大模型4.0
  • 原文地址:https://blog.csdn.net/ren9436/article/details/125602288