动态代理详解之JDK与CGLib

JDK 动态代理
Java API
InvocationHandler

java.lang.reflect.InvocationHandler,代理方法处理接口。每个代理实例对象都要关联一个 InvocationHandler,当调用方法执行到代理时,由重写的 InvocationHandler.invoke 方法作为实际的代理执行者。

public interface InvocationHandler {
    /**
    * @param proxy 代理实例对象($ProxyX extends Proxy implements some interface)
    * @param method 代理实例对象要调用的源目标方法(即拦截的方法,此处应指向代理的接口方法和Object的方法)
    * @param args 调用源目标方法时的入参
    */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
Proxy

java.lang.reflect.Proxy,提供静态方法用于创建代理类和代理实例对象,并且是所有 JDK 动态代理类的父类。

public class Proxy implements java.io.Serializable {
    // 代理类的缓存
	private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
    
    // 代理实例对象的调用处理器(实际处理代理方法的执行者)
    protected InvocationHandler h;
    
    private Proxy() {}
    
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }
    
    /**
    * 创建代理类
    * 
    * @param loader 类加载器,一般传被代理类的类加载器
    * @param interfaces 代理的接口Class数组
    */
    @CallerSensitive
    public static Class<?> getProxyClass(ClassLoader loader,
                                         Class<?>... interfaces)
        throws IllegalArgumentException
    {
        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
		// 先从缓存找,没有创建代理类
        return getProxyClass0(loader, intfs);
    }
    
    /**
    * 创建代理实例对象
    * 
    * @param loader 类加载器,一般传被代理类的类加载器
    * @param interfaces 代理的接口Class数组
    * @param h 代理方法处理器   
    */
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h) 
                throws IllegalArgumentException
    {
        // ...
        Class<?> cl = getProxyClass0(loader, intfs);
        // ...
        // 使用构造方法(带InvocationHandler的构造方法),创建并返回代理实例对象
        return cons.newInstance(new Object[]{h});
    }
    
}
原理

Proxy 创建一个继承 Proxy 并实现指定接口的类 $ProxyX ,通过重写 InvocationHandler 的 invoke 方法,由 invoke 方法去代理指定接口的方法。

// Proxy内部静态类,根据提供的ClassLoader和Class<?>[] interfaces,创建并返回代理类
private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
    // ...
    // 代理类类名中X的系号值
    private static final AtomicLong nextUniqueNumber = new AtomicLong();
    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
        // ...
        // 创建代理类(自验证可以参照这个,将字节数组{即字节码的二进制数据}输出到文件{.class}中去,然后利用IDEA反编译看结果,如下面的$Proxy2示例)
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces, accessFlags);
        // native加载并返回类对象
        return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
    }
   
}
JDK 方式代理类字节码示例
public final class $Proxy2 extends Proxy implements Player {
    private static Method m1;
    private static Method m4;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            // ...Player接口的方法
            m3 = Class.forName("org.jk.business.model.proxy.Player").getMethod("playShow");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
    
    // 入参为InvocationHandler的构造方法,super调用Proxy中h的赋值
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    
    // ... 相关代理方法
    // 举例:toString、hashCode、equals等Object的方法也会被代理
    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);
        }
    }
    // ...
}
为什么要继承Proxy

通俗答案:

  • 代理实例对象需要持有 InvocationHandler ,如果不继承 Proxy 就需要在每个创建的代理类里都加上该属性,不是很好的实现抽象逻辑;
  • 判断对象或者类是否是被 JDK 代理过的结果,不好判断,如果继承了 Proxy 就可以通过判断是否为 Proxy 的子类来作为一部分依据。Proxy 提供了 Proxy.isProxyClass(Class<?> cl) 。
使用示例

(1)先获取代理类,再创建代理实例对象 Proxy.getProxyClass

// 声明接口
public interface IPlayer {
    String playShow();
    String fetchSalary();
}

@Getter
@Setter
public class MoviePlayer implements IPlayer {
    private String name;
    @Override
    public String playShow() {
        // do sth
        return "good";
    }
    
    @Override
    public String fetchSalary() {
        return "1爽";
    }
}

// 被代理对象的持有者,代理逻辑的真正执行者(实例将会被赋值给Proxy的属性 h)
@AllArgsConstructor
class PlayerHolder implements InvocationHandler {
    private IPlayer player;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // befor do sth
        // 注意:proxy是代理实例对象,不能直接method.invoke(proxy, args),这样会形成递归调用,最终栈溢出;因此使用Holder持有被代理对象的方式来调用源方法
        Object result = method.invoke(player, args);
        // after do sth
        return result;
    }
}

// 使用
@Test
public void testJDKProxyWhenGetProxyClass() {
    MoviePlayer moviePlayer = new MoviePlayer();
    // proxyClass使用构造器去创建实例
    Class<?> proxyClass = Proxy.getProxyClass(IPlayer.class.getClassLoader(), IPlayer.class);
    // playerProxyInstance:代理实例对象
    IPlayer playerProxyInstance = (IPlayer)proxyClass.getConstructor(InvocationHandler.class).newInstance(new PlayerHolder(moviePlayer));
}

(2)Proxy直接创建代理实例对象 Proxy.newProxyInstance

@Test
public void testJDKProxyWhenNewProxyInstance() {
    MoviePlayer moviePlayer = new MoviePlayer();
    IPlayer playerProxyInstance = (IPlayer)Proxy.newProxyInstance(IPlayer.class.getClassLoader(), new Class[]{IPlayer.class}, new PlayerHolder(moviePlayer));
}
CGLib 动态代理

通过动态地生成一个子类去覆盖所要代理的类(非 final 修饰的类和方法)。CGLib 底层使用了 ASM 来操作字节码生成新的类,ASM 使用类似 SAX 的解析器来实现高性能。

Java API
MethodInterceptor

org.springframework.cglib.proxy.MethodInterceptor ,代理方法处理接口,继承 Callback 接口

package org.springframework.cglib.proxy;

public interface Callback {
}

public interface MethodInterceptor extends Callback {
    /**
    * @param o 代理实例对象
    * @param method 被代理方法
    * @param objects 被代理方法入参
    * @param methodProxy 被代理方法对应的MethodProxy对象
    */
    Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable;
    
}
Enhancer

创建子类去实现方法的拦截。

public interface CallbackFilter {
    // method:被代理的方法;返回 Callback 数组对应的回调处理器的下标,即指定该方法用哪个 Callback回调处理(注意:这是创建代理类生成字节码时使用)
    int accept(Method method);

    boolean equals(Object var1);
}

public class Enhancer extends AbstractClassGenerator {
        // 被代理类
        private Class superclass;
	// 被代理接口
	private Class[] interfaces;
	// 回调过滤
	private CallbackFilter filter;
	// 回调函数
	private Callback[] callbacks;
    
	// 设置被代理的类(如果 superclass 是接口,则内部会调用 setInterfaces)
        public void setSuperclass(Class superclass) {
            // 。。。
        }
        public void setInterfaces(Class[] interfaces) {
         this.interfaces = interfaces;
     }
    
    	// 设置被代理的方法的回调过滤处理
    	public void setCallbackFilter(CallbackFilter filter) {
		this.filter = filter;
	}
    
   	 // 设置回调处理(即方法的拦截,真正的业务代理逻辑)
    	public void setCallbacks(Callback[] callbacks) {
		if (callbacks != null && callbacks.length == 0) {
			throw new IllegalArgumentException("Array cannot be empty");
		}
		this.callbacks = callbacks;
	}
    
    	// 创建代理类(ignore any callbacks that have been set)
    	public Class createClass() {
		classOnly = true;
		return (Class) createHelper();
	}
    
    	// 创建代理对象实例
    	public Object create() {
		classOnly = false;
		argumentTypes = null;
		return createHelper();
	}
    
    	// 用指定的构造方法创建代理对象实例
    	public Object create(Class[] argumentTypes, Object[] arguments) {
		classOnly = false;
		if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
			throw new IllegalArgumentException("Arguments must be non-null and of equal length");
		}
		this.argumentTypes = argumentTypes;
		this.arguments = arguments;
		return createHelper();
	}
    
    	private Object createHelper() {
		preValidate();
        // 根据类/接口、callback等信息,创建一个key,用key去判断代理类是否已缓存
		Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
				ReflectUtils.getNames(interfaces),
				filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
				callbackTypes,
				useFactory,
				interceptDuringConstruction,
				serialVersionUID);
		this.currentKey = key;
        // AbstractClassGenerator.create
		Object result = super.create(key);
		return result;
	}
    
    	/*
    * DefaultGeneratorStrategy.generate调用Enhancer.generateClass来完成真正的创建工作
    * 拼装字节码数据(关键步骤)
    */
    public void generateClass(ClassVisitor v) throws Exception {
        // ...
    }
    
}
AbstractClassGenerator

所有代码生成 CGLIB 实用程序的抽象类,包含代理类、代理对象的创建以及代理类的缓存等。

abstract public class AbstractClassGenerator<T> implements ClassGenerator {
	// 类加载器-代理类的缓存(静态变量)
    // 代理类生成策略
    // 代理类类名称生成策略
    // 影响代理类生成的一些变量
    
    // 。。。
    
    protected Object create(Object key) {
        // ...
        ClassLoaderData data = cache.get(loader);
		// ...
        Object obj = data.get(this, getUseCache());
        if (obj instanceof Class) {
            return firstInstance((Class) obj);
        }
        return nextInstance(obj);
    }
    
	//内部类ClassLoaderData
    protected static class ClassLoaderData {
        public ClassLoaderData(ClassLoader classLoader) {
            // 赋值属性generatedClasses的值(省略,细节看源码)
            public Object apply(AbstractClassGenerator gen) {
                Class klass = gen.generate(ClassLoaderData.this);
                // 最终调用子类Enhancer.wrapCachedClass(klass)
                return gen.wrapCachedClass(klass);
            }
            // 上面的data.get触发gen.generate
        }
    }
    
    // 执行代理类创建
    protected Class generate(ClassLoaderData data) {
        // ...
        // strategy可以自定义,当前默认 DefaultGeneratorStrategy.INSTANCE
        byte[] b = strategy.generate(this);
        String className = ClassNameReader.getClassName(new ClassReader(b));
        ProtectionDomain protectionDomain = getProtectionDomain();
        synchronized (classLoader) { // just in case
            // SPRING PATCH BEGIN
            gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass);
            // SPRING PATCH END
        }
        return gen;
    }
}
Factory

Enhancer 根据属性 useFactory 决定创建的代理类是否实现 Factory 接口,Factory 接口提供根据已创建的代理类来生成额外的代理实例对象。

public interface Factory {
    // 传入新的Callback,变更原代理类的回调函数
    Object newInstance(Callback var1);

    Object newInstance(Callback[] var1);

    Object newInstance(Class[] var1, Object[] var2, Callback[] var3);

    Callback getCallback(int var1);

    void setCallback(int var1, Callback var2);

    void setCallbacks(Callback[] var1);

    Callback[] getCallbacks();
}

CGLib创建代理类调用流程图(待补充)

原理

Enhancer 通过创建被代理类的子类,并设置Callback(MethodInterceptor)对目标方法进行增强,实现对目标对象的代理。

在代理类中,一个目标方法对应两个方法,如目标中方法为 playShow(),则代理类中会存在 CGLIB$playShow$X()playShow()。其中,CGLIB$playShow$X()方法 X 是序数,表示目标方法在所有被代理的目标方法中的排序,内部直接调用 super.playShow() 即直接调用目标类的方法,不进行增强; playShow() 则是调用对应的 MethodInterceptor.intercept(...)完成代理增强任务。

与 JDK 动态代理一样,toString 等方法也会被代理。

CGLib 方式代理类字节码示例
public class MoviePlayer$$EnhancerByCGLIB$$d021d817 extends MoviePlayer implements Factory {
    private boolean CGLIB$BOUND;
    public static Object CGLIB$FACTORY_DATA;
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    // 回调方法数组,代理类构建时Enhancer的参数值
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    // 回调方法进行目标方法拦截,代理增强,每个Callback对应一个MethodInterceptor属性
    private MethodInterceptor CGLIB$CALLBACK_0;
    private MethodInterceptor CGLIB$CALLBACK_1;
    private MethodInterceptor CGLIB$CALLBACK_2;
    // 。。。
    private static final Object[] CGLIB$emptyArgs;
    private static final Method CGLIB$fetchSalary$1$Method;
    private static final MethodProxy CGLIB$fetchSalary$1$Proxy;
    // CGLIB$playShow$2$Method:目标方法playShow的源Method对象
    private static final Method CGLIB$playShow$2$Method;
    // CGLIB$playShow$2$Proxy:目标方法playShow的MethodProxy对象
    private static final MethodProxy CGLIB$playShow$2$Proxy;
    // 。。。
    
    static {
        CGLIB$STATICHOOK1();
    }
    static void CGLIB$STATICHOOK1() {
        // CGLIB$THREAD_CALLBACKS:useFactory时,可以用Factory的方法设置Callback,这里的ThreadLocal就用来在创建新代理对象实例的时候,newInstance(...)防止其他线程的干扰。
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        // var0:代理类Class对象;var1:目标类Class对象
        Class var0 = Class.forName("org.jk.business.model.proxy.MoviePlayer$$EnhancerByCGLIB$$d021d817");
        Class var1;
        
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"setName", "(Ljava/lang/String;)V", "fetchSalary", "()Ljava/lang/String;", "playShow", "()Ljava/lang/String;"}, (var1 = Class.forName("org.jk.business.model.proxy.MoviePlayer")).getDeclaredMethods());
    	// 。。。
        CGLIB$playShow$2$Method = var10000[2];
        CGLIB$playShow$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "playShow", "CGLIB$playShow$2");
		// 。。。
    }
    
    // 代理类的构造方法
     public MoviePlayer$$EnhancerByCGLIB$$d021d817() {
        CGLIB$BIND_CALLBACKS(this);
    }

    public MoviePlayer$$EnhancerByCGLIB$$d021d817(String var1) {
        super(var1);
        CGLIB$BIND_CALLBACKS(this);
    }
    
    // 为callback绑定methodinterceptor值
    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        MoviePlayer$$EnhancerByCGLIB$$d021d817 var1 = (MoviePlayer$$EnhancerByCGLIB$$d021d817)var0;
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            // 判断threadlocal中有没有,没有取代理类创建的默认值(即Enhancer构建时的参数)
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }

            Callback[] var10001 = (Callback[])var10000;
            var1.CGLIB$CALLBACK_3 = (MethodInterceptor)((Callback[])var10000)[3];
            var1.CGLIB$CALLBACK_2 = (MethodInterceptor)var10001[2];
            var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
        }

    }
    
    // 。。。
    /**
    * 目标方法对应代理类中的2个方法:CGLIB$playShow$2、playShow
    * CGLIB$playShow$2 直接调用父类的方法,相当于没有进行增强;
    * playShow 使用MethodInterceptor进行了增强
    */
    final String CGLIB$playShow$2() {
        return super.playShow();
    }

    public final String playShow() {
        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$playShow$2$Method, CGLIB$emptyArgs, CGLIB$playShow$2$Proxy) : super.playShow();
    }
    // 。。。
    
    
}
MethodProxy

当拦截到被代理方法时,代理类方法将 MethodProxy 对象作为入参传递给 MethodInterceptor.intercept(),MethodProxy.invoke 和 MethodProxy.invokeSuper 负责调用目标方法,MethodProxy中则通过 FastClass 的机制进行方法调用的优化。

通过 FastClass 代理类加方法索引下标的方式,实现了从反射调用到直接调用的转变。

启动VM参数配置 -Dcglib.debugLocation=F:\ 即可将字节码文件输出到指定目录下。

public class MethodProxy {
	private Signature sig1;

	private Signature sig2;

	private CreateInfo createInfo;

	private final Object initLock = new Object();

 // 通过 FastClassInfo 优化目标方法的执行
	private volatile FastClassInfo fastClassInfo;
 
 // 。。。
 
 private static class FastClassInfo {
		// 目标类的 FastClass 代理类对象
		FastClass f1;

     // 代理类的 FastClass 代理类对象
		FastClass f2;

     // 目标方法对应的第一个代理方法(如上面的CGLIB$playShow$2)在 f1 中的方法索引下标
		int i1;

     // 目标方法对应的第二个代理方法(如上面的playShow)在 f2 中的方法索引下标
		int i2;
	}
 
 
 private void init() {
		if (fastClassInfo == null) {
			synchronized (initLock) {
				if (fastClassInfo == null) {
					CreateInfo ci = createInfo;
					// 创建FastClassInfo和对应的FastClass信息(helper里也是动态代理,因此对于同一个目标类会有FastClass的缓存)
					FastClassInfo fci = new FastClassInfo();
					fci.f1 = helper(ci, ci.c1);
					fci.f2 = helper(ci, ci.c2);
                 // 获取对应方法签名的方法索引下标
					fci.i1 = fci.f1.getIndex(sig1);
					fci.i2 = fci.f2.getIndex(sig2);
					fastClassInfo = fci;
					createInfo = null;
				}
			}
		}
	}
 
 // 将会调用代理类中的 CGLIB$xxx$x()方法
 public Object invokeSuper(Object obj, Object[] args) throws Throwable {
		try {
			init();
			FastClassInfo fci = fastClassInfo;
         // 调用 FastClass 代理类对象的 invoke 方法,传入方法索引下标、目标代理类实例对象、方法参数
			return fci.f2.invoke(fci.i2, obj, args);
		}
		catch (InvocationTargetException e) {
			throw e.getTargetException();
		}
	}

}
FastClass 代理类字节码示例

本示例是代理类的 FastClass 代理类对象的示例

public class MoviePlayer$$EnhancerByCGLIB$$1a11a229$$FastClassByCGLIB$$339c2fad extends FastClass {
    public MoviePlayer$$EnhancerByCGLIB$$1a11a229$$FastClassByCGLIB$$339c2fad(Class var1) {
        super(var1);
    }
    
    public int getIndex(String var1, Class[] var2) {
        switch(var1.hashCode()) {
        case -679231402:
            if (var1.equals("playShow")) {
                switch(var2.length) {
                case 0:
                    return 8;
                }
            }
            break;
        case -137950106:
            if (var1.equals("CGLIB$playShow$2")) {
                switch(var2.length) {
                case 0:
                    return 20;
                }
            }
            break;
        }
        // ...
    }
    
    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        // var2是MethodProxy中 invokeSuper 传入的值,强转为代理类
        MoviePlayer$$EnhancerByCGLIB$$d021d817 var10000 = (MoviePlayer$$EnhancerByCGLIB$$d021d817)var2;
        int var10001 = var1;

        try {
            switch(var10001) {
                // ...
                case 8:
                return var10000.playShow(); 
                // ...
                // 根据对应下标,调用对应的目标代理类的方法,不再是反射调用的方式
                case 20:
                return var10000.CGLIB$playShow$2();
                // ...
            }
        }
        
    }
    
}

代理实例对象 invokeSuper 调用流程图(待补充)

使用示例
// 声明接口
public interface IPlayer {
    String playShow();
    String fetchSalary();
}

// 目标类
@Getter
@Setter
public class MoviePlayer implements IPlayer {
    private String name;
    @Override
    public String playShow() {
        // do sth
        return "good";
    }
    
    @Override
    public String fetchSalary() {
        return "1爽";
    }
}

// 代理类创建工具
public class PlayerCglibProxy {
    // 根据目标对象创建代理对象
    public Object getIPlayerInstance(IPlayer player) throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(player.getClass());
        
        // 设置4个方法拦截(前面3个是为了体现 callbackFilter 的作用)
        enhancer.setCallbacks(new Callback[]{createCallback("callback1"), createCallback("callback2"), createCallback("callback3"), 
        new PlayerHolder(player)});
        
        // 设置拦截过滤,对于指定方法选择指定的callback处理
        enhancer.setCallbackFilter(new CallbackFilter() {
            Random random = new Random();

            @Override
            public int accept(Method method) {
                // 如果不是playShow,则从Callback[]随机选择一个callback,0-2
                if (!method.getName().equals("playShow")) {
                    return random.nextInt(3);
                }
                return 3;
            }
        });
        
        // 创建代理实例对象
        return enhancer.create();
    }
    
    private MethodInterceptor createCallback(String displayName) {
        return new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println(displayName);
                return method.invoke(target, objects);
            }
        };
    }
    
    @AllArgsConstructor
	class PlayerHolder implements MethodInterceptor {
        private IPlayer player;
        
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            // befor do sth
            Object result = methodProxy.invokeSuper(o, objects);
            // 或者(这样就走的反射):Object result = method.invoke(player, objects);
            // after do sth
            return result;
        }
	}
}

@Test
public void testJDKProxyWhenNewProxyInstance() {
    MoviePlayer moviePlayer = new MoviePlayer();
    PlayerCglibProxy proxy = new PlayerCglibProxy();
    IPlayer playerProxyInstance = (IPlayer)proxy.getIPlayerInstance(moviePlayer);
}
两种动态代理方式对比

(1)继承关系:JDK 方式需要目标类提供接口,生成的代理类继承 Proxy 并实现指定的接口;CGLib 方式不需要目标类一定提供接口,生成的代理类继承目标类(也可以只提供接口,不提供目标类);因此 CGLib 可以为没有实现接口的目标类进行代理增强,更加灵活一些。

(2)调用方式:JDK 方式使用反射的机制去调用目标方法,CGLib 使用 FastClass 代理类对象直接调用目标方法,理论上效率更高(但目前高版本的 JDK 测试中,JDK 方式效率甚至比 CGLib 高,这点还需要继续验证。)

参考文档

JDK动态代理

CGLib动态代理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值