Spring源碼分析之——AOP動態代理的選擇

上一篇《Spring源碼分析之——AOP的原理及初始化細節》講到AOP的原理和細節,這一篇補充一下動態代理的選擇代碼細節。

我們知道動態代理分兩種,JDK動態代理和Cglib動態代理,那麼Spring選用的哪個呢?

 

右半部分可以看到AopProxy下面有Cglib和JDK兩種,至於創建哪種,是左邊工廠DefaultAopProxyFactory負責創建的,帶着這個圖看源碼。

1、後置處理器判斷是否需要動態代理,判斷的依據是Bean是否有配置Advisor;

2、如果需要代理,則構造ProxyFactory對象;

2、通過ProxyFactory對象的父類方法getAopProxyFactory找到AopProxyFactory對象,默認DefaultAopProxyFactory;

3、通過工廠創建實際的代理對象(createAopProxy);

——就這麼簡單。

 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

——從createProxy方法開始看 

// 如果需要代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
 
    // Create proxy if we have advice.
    // 怎麼判斷是否需要代理?這裏給出了答案:如果有配置Advisers則需要被代理
    // 這裏開始去找Advice,Advisor,如果配置了,同時當前的Bean符合要求,就要動態代理
    // 這裏說的符合要求,就是advisor配置的正則表達式是否匹配上
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        // 有顧問的Bean,cacheKey=被代理BeanName
        this.advisedBeans.put(cacheKey, Boolean.TRUE);

        // ★★★★★★ 創建代理 ★★★★★★
        Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }
    // 否則,設置不需要顧問
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    }

    // 首先構造一個ProxyFactory工廠,此工廠提供方法getProxy獲取代理對象
    // 但其細節是通過其父類先得到AopProxy的工廠,再通過工廠創建AopProxy,再通過AopProxy得到代理對象
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    return proxyFactory.getProxy(getProxyClassLoader());
}

 

org.springframework.aop.framework.ProxyFactory

public Object getProxy(ClassLoader classLoader) {
    // createAopProxy是父類方法
    // 1、先創建AopProxy
    // 2、再創建代理對象
    return createAopProxy().getProxy(classLoader);
}

 

進入父類:

org.springframework.aop.framework.ProxyCreatorSupport

public class ProxyCreatorSupport extends AdvisedSupport {

    private AopProxyFactory aopProxyFactory;

    /**
     * Create a new ProxyCreatorSupport instance.
     */
    public ProxyCreatorSupport() {
        // 默認實現: DefaultAopProxyFactory
        this.aopProxyFactory = new DefaultAopProxyFactory();
    }

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        // 默認AopProxyFactory是:DefaultAopProxyFactory,也只有這一個
        return getAopProxyFactory().createAopProxy(this);
    }

    /**
     * Return the AopProxyFactory that this ProxyConfig uses.
     */
    public AopProxyFactory getAopProxyFactory() {
        // 返回默認的DefaultAopProxyFactory
        return this.aopProxyFactory;
    }
}

 

org.springframework.aop.framework.DefaultAopProxyFactory

// 這段代碼有前人解釋的很好了
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    //這段代碼用來判斷選擇哪種創建代理對象的方式
    //config.isOptimize()   是否對代理類的生成使用策略優化 其作用是和isProxyTargetClass是一樣的 默認爲false
    //config.isProxyTargetClass() 是否使用Cglib的方式創建代理對象 默認爲false
    //hasNoUserSuppliedProxyInterfaces目標類是否有接口存在 且只有一個接口的時候接口類型不是
    //SpringProxy類型 
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        //上面的三個方法有一個爲true的話,則進入到這裏
        //從AdvisedSupport中獲取目標類 類對象
        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的方式生成代理對象
        //如果目標類是Proxy類型 則還是使用JDK的方式生成代理對象
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config);
        }
        //配置了使用Cglib進行動態代理  或者目標類沒有接口 那麼使用Cglib的方式創建代理對象
        return new ObjenesisCglibAopProxy(config);
    }
    else {
        //上面的三個方法沒有一個爲true 那使用JDK的提供的代理方式生成代理對象
        return new JdkDynamicAopProxy(config);
    }
}

 

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