深入剖析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代理速度是相差無幾的。

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