Spring中JDK動態代理和Cglib代理的區別

    Spring的AOP基於代理模式,而且它即便用到了JDK動態代理也使用了Cglib代理。java

    以下代碼是springAOP中默認的代理實現類DefaultAopProxyFactory,其中建立代理的方法createAopProxy,在這個方法中Spring經過判斷targetClass是否有實現接口來肯定使用哪種代理,若是實現了接口則使用JDK動態代理,若是沒有實現接口則使用Cglib代理。同時JdkDynamicAopProxy爲JDK動態代理的生成類,ObjenesisCglibAopProxy能夠生成Cglib代理。spring

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public DefaultAopProxyFactory() {
    }

	//建立代理
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);//生成JDK動態代理
        } else {
            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.");
            } else {//ObjenesisCglibAopProxy生成Cglib代理
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

    從上面代碼能夠發現當須要被代理的類實現了接口的時候Spring會使用動態代理,當被代理的類沒有接口實現的時候使用的是Cglib,咱們也能夠強制使用CGlib,在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>。框架

    性能問題:因爲Cglib代理是利用ASM字節碼生成框架在內存中生成一個須要被代理類的子類完成代理,而JDK動態代理是利用反射原理完成動態代理,因此Cglib建立的動態代理對象性能比JDk動態代理動態建立出來的代理對象新能要好的多,可是對象建立的速度比JDk動態代理要慢,因此,當Spring使用的是單例狀況下能夠選用Cglib代理,反之使用JDK動態代理更加合適。同時還有一個問題,被final修飾的類只能使用JDK動態代理,由於被final修飾的類不能被繼承,而Cglib則是利用的繼承原理實現代理的。性能

關於動態代理請參考:https://my.oschina.net/zicheng/blog/1920396ui

相關文章
相關標籤/搜索