深入剖析spring代理工厂创建代理对象

基础回顾

JDK是怎么创建代理对象的

JDK代理只能针对接口进行代理,因而被代理类必须先实现一个接口

public interface ActionService {

	/**
	 * who做something事情
	 * @param who
	 */
	void dosomething(String who);
}

danceAction 实现类

public class DanceActionService implements ActionService {
	@Override
	public void dosomething(String who) {
		System.out.println(who+"跳舞ing...");
	}
}
public class JDKProxyTest {
	public static void main(String[] args) throws InterruptedException {

		final ActionService actionService = new DanceActionService();
		Object proxyInstance = Proxy
				.newProxyInstance(DanceActionService.class.getClassLoader(), DanceActionService.class.getInterfaces(),
						(proxy, method, arguments) -> {
							// 可以在这里植入我们的逻辑
							return method.invoke(actionService, arguments);
						});

		System.out.println(proxyInstance.getClass());
		((ActionService)proxyInstance).dosomething("我");
		System.out.println(Proxy.isProxyClass(proxyInstance.getClass()));
		Thread.sleep(9999999999L);
	}
}

运行结果最终会打印出:“我跳舞ing…”
至此我不想解释太多,因为这段代码真的很基础,不明白的同学先去看看相关资料的。

// 上面一段代码到底做了什么,实则是在内存中生成一份class,代理对象则是该内存class的实例,生成的class文件如下:

package com.sun.proxy;

import com.atguigu.test.advisor.ActionService;
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 ActionService {
    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.atguigu.test.advisor.ActionService").getMethod("dosomething", Class.forName("java.lang.String"));
            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 dosomething(String string) {
        try {
		// this.h 指的是父类Proxy中InvocationHandler对象
            this.h.invoke(this, m3, new Object[]{string});
            return;
        }
        catch (Error | RuntimeException throwable) {
            throw throwable;
        }
        catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }
}

重点关注dosomething方法,this.h 指的是父类Proxy中InvocationHandler对象,this指向代理对象,m3反射方法,new Object[]{string}是我们方法的参数。

CGLIB代理

除了官方的JDK代理,民间还有CGLIB代理方式,cglib框架底层基于java asm字节码技术,在过去经常听闻jdk代理比cglib代理要慢,事实真的是这样吗?在文末我们将实际测试,一般来说官方的是会随着jdk版本的升级而不断优化的,说xxx比xxx优秀,也许官方早就做了优化,就行jdk1.6之前的synchronize和reentranLock锁一样。

  • JDK代理要求被代理者至少实现一个接口,而cglib代理则没有这一要求,cglib会生成一个类继承目标类。
  • JDK代理需要借助目标对象创建代理,如上文需要先实例化目标对象,而cglib代理不需要。

callback

为了理解cglib,需要先明白cglib的callback。callback是cglib对创建代理对象方式的逻辑抽象概念,总共分为六种。其次还有callbackFilter,供我们实现接口,定义那些方法该被拦截。

  • FixedValue
  • InvocationHandler
  • LazyLoader
  • MethodInterceptor
  • Dispatcher
  • NoOp 接口声明了一个单例对象,该代理不对被代理类执行任何操作
    其中最常用的是MethodInterceptor callback ,它允许我们完全自定义拦截方式,不同的callback,需要实现的invoke方法也不一样,大家可以查阅下api。由于我们经常使用Spring,spring自己集成callback的组件,在这六大callback基础上还增加了ConditionalCallback 条件callback,决定哪些方法会被拦截,其本质也是结合callback和callbackFilter实现,本文也是基于spring cglib组件运行的。

CGLIB的使用

  • 引入spring-core核心依赖
  • 编写目标类
/**
 *
 * 目标类(需要被代理的类)
 *@author Evan
 *@since 2020/6/12 23:19
 */
public class DanceActionService implements ActionService {
	@Override
	public void dosomething(String who) {
		System.out.println(who+"跳舞ing...");
	}
}
  • 代理类测试

/**
 * Enhancer 生成代理对象测试
 *@author Evan
 *@since 2020/6/13 19:23
 */
public class EnhancerTest {

	public static void main(String[] args) throws InterruptedException {
		final DanceActionService delegate = new DanceActionService();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(DanceActionService.class);
		//cglib提供了6种callback
//		enhancer.setCallback(NoOp.INSTANCE);
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			/**
			 * @param Object obj  cglib生成的代理对象
			 * @param Method arguments 目标对象方法,例如,doSomething
			 * @param Object[] objects 参数
			 * @param MethodProxy methodProxy 代理对象方法
			 */
			public Object intercept(Object obj, Method method, Object[] arguments, MethodProxy methodProxy)
					throws Throwable {
				// 植入我们的逻辑
				System.out.println(methodProxy.getSignature().getName()+"方法被调用");
				// 调用目标方法
				return methodProxy.invokeSuper(obj,arguments);
				// 和jdk代理不同,不要这里调用反射方法,因为这里的obj不是目标对象,而是代理对象
				// 如果非要这样用,得想办法把目标对象传进来
//				return method.invoke(delegate,arguments);
			}
		});
		DanceActionService proxy = (DanceActionService) enhancer.create();

		proxy.dosomething("我");

	}
}

接下来 我们看一下,生成的代理类究竟是什么样子的?

package com.atguigu.test.advisor;

import com.atguigu.test.advisor.DanceActionService;
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class DanceActionService$$EnhancerByCGLIB$$c0a31786
extends DanceActionService
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$dosomething$0$Method;
    private static final MethodProxy CGLIB$dosomething$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;

    public DanceActionService$$EnhancerByCGLIB$$c0a31786() {
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = this;
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(danceActionService$$EnhancerByCGLIB$$c0a31786);
    }

    static {
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$STATICHOOK1();
    }

    public final boolean equals(Object object) {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {
            DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            Object object2 = methodInterceptor.intercept(this, CGLIB$equals$1$Method, new Object[]{object}, CGLIB$equals$1$Proxy);
            return object2 == null ? false : (Boolean)object2;
        }
        return super.equals(object);
    }

    public final String toString() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {
            DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            return (String)methodInterceptor.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy);
        }
        return super.toString();
    }

    public final int hashCode() {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {
            DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            Object object = methodInterceptor.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
            return object == null ? 0 : ((Number)object).intValue();
        }
        return super.hashCode();
    }

    protected final Object clone() throws CloneNotSupportedException {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {
            DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            return methodInterceptor.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy);
        }
        return super.clone();
    }

    public Object newInstance(Callback[] arrcallback) {
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(arrcallback);
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = new DanceActionService$$EnhancerByCGLIB$$c0a31786();
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(null);
        return danceActionService$$EnhancerByCGLIB$$c0a31786;
    }

    public Object newInstance(Callback callback) {
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = new DanceActionService$$EnhancerByCGLIB$$c0a31786();
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(null);
        return danceActionService$$EnhancerByCGLIB$$c0a31786;
    }

    public Object newInstance(Class[] arrclass, Object[] arrobject, Callback[] arrcallback) {
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786;
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(arrcallback);
        Class[] arrclass2 = arrclass;
        switch (arrclass.length) {
            case 0: {
                danceActionService$$EnhancerByCGLIB$$c0a31786 = new DanceActionService$$EnhancerByCGLIB$$c0a31786();
                break;
            }
            default: {
                throw new IllegalArgumentException("Constructor not found");
            }
        }
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$SET_THREAD_CALLBACKS(null);
        return danceActionService$$EnhancerByCGLIB$$c0a31786;
    }

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

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

    public final void dosomething(String string) {
        MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
        if (methodInterceptor == null) {
            DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
            methodInterceptor = this.CGLIB$CALLBACK_0;
        }
        if (methodInterceptor != null) {
            Object object = methodInterceptor.intercept(this, CGLIB$dosomething$0$Method, new Object[]{string}, CGLIB$dosomething$0$Proxy);
            return;
        }
        super.dosomething(string);
    }

    public void setCallback(int n, Callback callback) {
        switch (n) {
            case 0: {
                this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;
                break;
            }
        }
    }

    public void setCallbacks(Callback[] arrcallback) {
        Callback[] arrcallback2 = arrcallback;
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = this;
        this.CGLIB$CALLBACK_0 = (MethodInterceptor)arrcallback[0];
    }

    public Callback getCallback(int n) {
        MethodInterceptor methodInterceptor;
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
        switch (n) {
            case 0: {
                methodInterceptor = this.CGLIB$CALLBACK_0;
                break;
            }
            default: {
                methodInterceptor = null;
            }
        }
        return methodInterceptor;
    }

    public Callback[] getCallbacks() {
        DanceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BIND_CALLBACKS(this);
        DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = this;
        return new Callback[]{this.CGLIB$CALLBACK_0};
    }

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

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        Class<?> class_ = Class.forName("com.atguigu.test.advisor.DanceActionService$$EnhancerByCGLIB$$c0a31786");
        Class<?> class_2 = Class.forName("com.atguigu.test.advisor.DanceActionService");
        CGLIB$dosomething$0$Method = ReflectUtils.findMethods(new String[]{"dosomething", "(Ljava/lang/String;)V"}, class_2.getDeclaredMethods())[0];
        CGLIB$dosomething$0$Proxy = MethodProxy.create(class_2, class_, "(Ljava/lang/String;)V", "dosomething", "CGLIB$dosomething$0");
        class_2 = Class.forName("java.lang.Object");
        Method[] arrmethod = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, class_2.getDeclaredMethods());
        CGLIB$equals$1$Method = arrmethod[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(class_2, class_, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = arrmethod[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(class_2, class_, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = arrmethod[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(class_2, class_, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = arrmethod[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(class_2, class_, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
    }

    private static final void CGLIB$BIND_CALLBACKS(Object object) {
        block2: {
            Object object2;
            block3: {
                DanceActionService$$EnhancerByCGLIB$$c0a31786 danceActionService$$EnhancerByCGLIB$$c0a31786 = (DanceActionService$$EnhancerByCGLIB$$c0a31786)object;
                if (danceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BOUND) break block2;
                danceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$BOUND = true;
                object2 = CGLIB$THREAD_CALLBACKS.get();
                if (object2 != null) break block3;
                object2 = CGLIB$STATIC_CALLBACKS;
                if (CGLIB$STATIC_CALLBACKS == null) break block2;
            }
            danceActionService$$EnhancerByCGLIB$$c0a31786.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])object2)[0];
        }
    }

    final void CGLIB$dosomething$0(String string) {
        super.dosomething(string);
    }

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

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

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

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

利用Spring代理工厂创建自己的代理对象

前面介绍了创建代理对象的两种方式,那么我们想要在spring应用中怎么创建自己的代理对象呢?当然你完全可以按照上面说的两种方式创建好代理对象,然后定义BeanPostProcess组件,在后初始化方法里把目标的对象替换成代理对象,然后注册到容器中,当然我们还可以做得更好,spring本身就提供了代理工厂类,接下来我们看一下如何实现。

Spring中面向Aop编程有一组抽象的概念:

  • 执行点(Executepoint) - 类初始化,方法调用。
  • 连接点(Joinpoint) - 执行点+方位的组合,可确定Joinpoint,比如类开始初始化前,类初始化后,方法调用前,方法调用后。
  • 切点(Pointcut) - 在众多执行点中,定位感兴趣的执行点。Executepoint相当于数据库表中的记录,而Pointcut相当于查询条件。
  • 增强(Advice) - 织入到目标类连接点上的一段程序代码。除了一段程序代码外,还拥有执行点的方位信息。
  • 目标对象(Target) - 增强逻辑的织入目标类
  • 引介(Introduction) - 一种特殊的增强(advice),它为类添加一些额外的属性和方法,动态为业务类添加其他接口的实现逻辑,让业务类成为这个接口的实现类。
  • 代理(Proxy) - 一个类被AOP织入后,产生一个结果类,它便是融合了原类和增强逻辑的代理类。
  • 切面(Aspect) - 切面由切点(Pointcut)和增强(Advice/Introduction)组成,既包括横切逻辑定义,也包括连接点定义。

为了创建代理我们需要向spring提供Advisor,advisor是一种特殊的Aspect只有一个切点和一个增强。

定义advisor

// @Component 在main函数中测试,因此不需要
public class LogAdvisor implements PointcutAdvisor,BeanFactoryAware {
	@Override
	public Pointcut getPointcut() {
		return new Pointcut() {
			@Override
			public ClassFilter getClassFilter() {
				return ClassFilter.TRUE;
			}

			@Override
			public MethodMatcher getMethodMatcher() {
				return new MethodMatcher() {
					@Override
					public boolean matches(Method method, Class<?> targetClass) {
						//只拦截了mylogin方法
						String methodName = method.getName();
						if ("mylogin".equals(methodName)) {
							return true;
						}
						return false;
					}

					@Override
					public boolean isRuntime() {
						return false;
					}

					@Override
					public boolean matches(Method method, Class<?> targetClass, Object... args) {
						return false;
					}
				};
			}
		};
	}

	@Override
	public Advice getAdvice() {
		return new MethodBeforeAdvice() {
			@Override
			public void before(Method method, Object[] args, Object target) throws Throwable {
				System.out.println("BeforeAdvice实现,在目标方法被调用前调用,目标方法是:" + method.getDeclaringClass().getName() + "."
						+ method.getName());
			}
		};
	}

	@Override
	public boolean isPerInstance() {
		return true;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

	}
}

main函数中测试

public class ProxyTest {
	public static void main(String[] args) {
		//	创建代理方式
			AccountService accountService = new AccountService();
			AdvisedSupport support = new AdvisedSupport();
			support.addAdvisor(new LogAdvisor());
		// 设目标类
			support.setTarget(accountService);
			ProxyCreatorSupport proxyCreatorSupport = new ProxyCreatorSupport();
			AopProxyFactory aopProxyFactory = proxyCreatorSupport.getAopProxyFactory();
			AopProxy aopProxy = aopProxyFactory.createAopProxy(support);
			AccountService proxy = (AccountService) aopProxy.getProxy();
			proxy.mylogin();

	}
}

接下来我们看下源码是怎么创建代理对象的?

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			//重点看这里,使用jdk代理,如果目标类是接口或者是已经被JDK代理过
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

isProxyClass源码

 public static boolean isProxyClass(Class<?> cl) {
	 isAssignableFrom判断目标对象所属的类是不是Proxy类或者是其子类,由于jdk代理生成的类都会继承Proy
        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
    }

结论:

  • 如果目标类是接口或者其实例是JDK代理对象,则使用JDK代理。
  • 其它情况使用cglib代理。

cglib 和jdk代理的性能比较

在我的window笔记本,jdk1.8 ,jdk代理和cglib代理速度是相差无几的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章