Spring AOP DefaultAdvisorAutoProxyCreator

Spring AOP源碼目錄

Spring AOP源碼01:Jdk動態(tài)代理底層源碼
Spring AOP源碼02:ProxyFactory
Spring AOP源碼03:JdkDynamicAopProxy
Spring AOP源碼04:MethodInvocation 攔截器調用
Spring AOP源碼05:DefaultAdvisorAutoProxyCreator
Spring期末考壓軸題:當Spring AOP遇上循環(huán)依賴
git注釋源碼地址:https://github.com/chaitou/spring-framework-master.git

前言

前面已經(jīng)學習了ProxyFactory的源碼,學習了如何手動硬編碼使用最基礎的Spring AOP,以及實現(xiàn)方式。這一節(jié)要學習自動代理DefaultAdvisorAutoProxyCreator源碼。比起Spring AOP注解形式實現(xiàn)自動代理,我們之前學習的ProxyFactory還差以下2步:

  1. 代理時機:在Spring Ioc創(chuàng)建Bean的過程中,尋找合適的時機進行調用Spring AOP進行代理
  2. 自動代理:搜索所有bean中注解了@Aspect的類,并且提取Advisor(切面)。當一個正常的bean創(chuàng)建時,從這些候選的Advisor(切面)通過Pointcut尋找與之匹配的Advice,最后生成攔截器,再調用Proxy.getProxy()獲取代理

一、代理時機

這一點應該引起大家的注意,因為很多書以及博客都沒有講明白,都是簡單的一筆帶過,但是筆者卻認為如果連代理時機都弄不清楚,還談什么自動代理呢?

1. DefaultAdvisorAutoProxyCreator類圖

!](https://upload-images.jianshu.io/upload_images/8190955-bc261b8789f5ad01?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
之前的Spring Ioc源碼專題的生命周期中提到過這么一段話:

spring使用模板模式,在bean的創(chuàng)建過程中安插了許多錨點,用戶尋找對應的錨點,通過重寫方法介入到bean的創(chuàng)建過程當中。

想要介入Spring Ioc創(chuàng)建Bean的過程,最好的方式就是實現(xiàn)BeanPostProcessor,想必Spring AOP也正式通過這種方式介入Bean的創(chuàng)建,實現(xiàn)自動代理的吧??梢钥吹?code>DefaultAdvisorAutoProxyCreator類圖最左邊的分支上就實現(xiàn)了SmartInstantiationAwareBeanPostProcessor,在DefaultAdvisorAutoProxyCreator的父類AbstractAutoProxyCreator中,我們找到了其實現(xiàn)的后置方法

AbstractAutoProxyCreator

  • postProcessBeforeInitialization 初始化前擴展
  • postProcessAfterInitialization 初始化后擴展
  • postProcessBeforeInstantiation 對象實例化前擴展
  • postProcessAfterInstantiation 對象實例化后擴展
  • postProcessPropertyValues 屬性依賴注入前擴展

5個后置處理器,只有2個有具體的實現(xiàn),分別是postProcessBeforeInstantiation實例化前和postProcessAfterInitialization初始化后

2. 源碼分析

我們從Spring Ioc創(chuàng)建開始跟中,在創(chuàng)建bean

// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
         throws BeanCreationException {

      // 省略無關代碼...

      try {
         // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
         /**
          * 實例化前的后置處理器
          * 給BeanPostProcessors一個機會返回代理替換調真實的實例,主要是來執(zhí)行實現(xiàn)了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor
          *
          * ① 重點:
          * AOP代理時機 1. 當用戶自定義TargetSource將會在實例化前進行代理,此時的TargetSource直接返回需要被代理的Bean,也就是說該被代理的Bean的實例化初始化操作均由自己負責。并進行短路操作
          * 2. 用戶不自定義TargetSource時則返回空,在初始化后才進行AOP代理
          */
         Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
         // ② 如果此時返回的bean不為空,直接短路,不再進行bean的實例化、填充、初始化!
         if (bean != null) {
            return bean;
         }
      }
      catch (Throwable ex) {
         throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
               "BeanPostProcessor before instantiation of bean failed", ex);
      }

      try {
         // 核心邏輯
         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
         if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
         }
         return beanInstance;
      }
      ...
   }

① 在bean實例化前的這個操作非常重要,之前我們在Spring Ioc時說,這邊一般都返回空,但是什么時候不返回空呢?帶著這個問題繼續(xù)往下看源碼

② 當不為空時,直接就return了!也就是說bean直接就不實例化、填充、初始化了!

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        // 確認bean在初始化階段之前
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                // 確認當前beanName所要返回的最終類型
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    // 只有前置處理返回的bean不為null, 才進行初始化后置處理(Aop的代理在初始化后置處理中進行)
                    // 但是除非bean自定義了TargetSource,否則前置處理返回的bean為空
                    // 一般沒有自定義TargetSource情況下,是不會在實例化前調用該后置處理,也不會導致后續(xù)短路操作!
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        // 實例化后置處理
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

前面我們提到5個后置處理器,只有2個有具體的實現(xiàn),分別是postProcessBeforeInstantiation實例化前和postProcessAfterInitialization初始化后,跟上方代碼已經(jīng)完全對上了。接下來我們就去AbstractAutoProxyCreator中看看這2個后置處理器到底做了什么工作

3. postProcessBeforeInstantiation

// AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
      // 省略無關代碼... 

      /**
       * 如果我們有自定義的TargetSource,在此處創(chuàng)建代理。
       * TargetSource將以自定義方式處理目標實例。
       */
      // 獲取自定義TargetSource
      TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
      if (targetSource != null) {
         if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
         }
         // 獲取攔截器
         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
         // 生成代理,跟之前說過的Proxy.getProxy一樣的
         Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
         // 實在緩存
         this.proxyTypes.put(cacheKey, proxy.getClass());
         // 返回代理
         return proxy;
      }

      return null;
   }

只有targetSource != null才會返回bean,也就是說只有自定義了targetSource,從而導致后續(xù)短路操作。自定義targetSource的意思就是說我們自己負責target的創(chuàng)建,不需要你Spring Ioc插手。那么targetSource到底有什么用呢?例如CommonsPoolTargetSource:可以池化TargetSource,每次執(zhí)行時從池中取代理對象,執(zhí)行完方法再返回池中,這里不扯遠

4. postProcessAfterInitialization

    // AbstractAutoProxyCreator.java
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // 緩存key,一般為beanClassName_beanName
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // bean如果有需要將會被AOP代理
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

5. 代理時機總結

  1. 當用戶自定義了targetSource,說明代理目標target由用戶自己負責窗口(包括實例化等步驟),因此在bean初始化前就會調用AbstractAutoProxyCreatorpostProcessBeforeInstantiation生成代理。生成后的代理已經(jīng)是完整形態(tài),因此,直接調用postProcessAfterInitialization對該代理進行完善,接著直接返回,進行短路操作!不需要再進行Spring Ioc創(chuàng)建bean的過程!
  2. 當用戶沒自定義targetSource時,那么這個步驟返回的便是null,則會進行Spring Ioc創(chuàng)建bean的標準程序,實例化、填充屬性、初始化。并且在postProcessAfterInitialization中調用wrapIfNecessary進行AOP代理

代理時機流程圖:


AOP代理時機

二、自動代理

上面已經(jīng)說了,代理時機分為2種,但是絕大部分情況還是使用的是第二種!也就是在初始化后進行AOP代理。上面在初始化后置處理器看到AOP通過wrapIfNecessary完成

// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        // 該bean已經(jīng)處理過了,則直接返回
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        // 無需被增強,也跳過
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        // 如果該bean是基礎類,或者指定了該bean不需要代理,則不進行代理,跳過
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // 1. 獲取增強攔截器
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 存在增強,則進行代理
        if (specificInterceptors != DO_NOT_PROXY) {
            // 緩存表明該bean需要被增強
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 2. 創(chuàng)建代理
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
        // 緩存表明bean已經(jīng)增強過
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

1. 獲取增強攔截器

    // AbstractAdvisorAutoProxyCreator.java 
    protected Object[] getAdvicesAndAdvisorsForBean(
            Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        // 1. 獲取所有Advisor 2. 在所有Advisor中挑選適用的Advisor
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 獲取所有Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 在所有Advisor中尋找適用于該bean的Advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
      // 對所有Advisor進行排序
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

1.1 findCandidateAdvisors

    // AnnotationAwareAspectJAutoProxyCreator.java
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        // 適用注解方式配置AOP,但是可能也還存在xml配置的AOP,因此調用父類方法加載xml中的AOP聲明
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            // 為所有注解了@Aspect類創(chuàng)建增強
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }
// BeanFactoryAspectJAdvisorsBuilder.java
public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = this.aspectBeanNames;//- 獲取Aspect切面的beanName

        // 說明還沒有緩存,需要從頭遍歷所有bean,找出注解了@Aspect的bean
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new ArrayList<>();
                    aspectNames = new ArrayList<>();
                    // 通過BeanFactory,也就是Ioc容器獲取所有的beanName
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    // 循環(huán)所有beanName
                    for (String beanName : beanNames) {
                        // 不合法的bean直接跳過,規(guī)則由子類定義
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        // We must be careful not to instantiate beans eagerly as in this case they
                        // would be cached by the Spring container but would not have been weaved.
                        // 獲取bean類型
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        // 該bean被Aspect注解
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);//- 緩存被Aspect注解的beanName
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            /**
                             * singleton:即切面只會有一個實例;
                             * perthis:每個切入點表達式匹配的連接點對應的AOP對象(代理對象)都會創(chuàng)建一個新切面實例;
                             * pertarget:每個切入點表達式匹配的連接點對應的目標對象都會創(chuàng)建一個新的切面實例
                             */
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                // 解析增強方法
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    // 如果bean是單例,則直接緩存Advisor
                                    this.advisorsCache.put(beanName, classAdvisors);
                                }
                                else {
                                    // 不是單例的情況下,只能緩存工廠,每次都取增強都得新生產(chǎn)一個
                                    this.aspectFactoryCache.put(beanName, factory);
                                }
                                // 添加Advisor
                                advisors.addAll(classAdvisors);
                            }
                            else {
                                // Per target or per this.
                                if (this.beanFactory.isSingleton(beanName)) {
                                    throw new IllegalArgumentException("Bean with name '" + beanName +
                                            "' is a singleton, but aspect instantiation model is not singleton");
                                }
                                MetadataAwareAspectInstanceFactory factory =
                                        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                                this.aspectFactoryCache.put(beanName, factory);
                                advisors.addAll(this.advisorFactory.getAdvisors(factory));
                            }
                        }
                    }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }

        if (aspectNames.isEmpty()) {
            return Collections.emptyList();
        }
        List<Advisor> advisors = new ArrayList<>();
        for (String aspectName : aspectNames) {
            // 從緩存中獲取增強
            List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                // 加入到列表中
                advisors.addAll(cachedAdvisors);
            }
            else {
                MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
        return advisors;
    }

1.2 findAdvisorsThatCanApply

    // AbstractAdvisorAutoProxyCreator.java
    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            // 匹配當前bean適用的advisors,只匹配到類,只有調用時JdkDynamicAopProxy.invoke才匹配到方法
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }
    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        //- 處理引介增強
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            //- 處理普通bean
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            // 獲取Pointcut跟targetClass做匹配
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }

創(chuàng)建代理流程圖:


在這里插入圖片描述

2. 創(chuàng)建代理

創(chuàng)建代理我們已經(jīng)詳解過ProxyFactory,設置接口,設置代理目標,設置增強,最后生成代理

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

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

        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);
        }
        // 創(chuàng)建代理,在之前的proxyFactory已經(jīng)詳解過
        return proxyFactory.getProxy(getProxyClassLoader());
    }

創(chuàng)建代理,這個接下去就很熟悉了

    public Object getProxy(@Nullable ClassLoader classLoader) {
        return createAopProxy().getProxy(classLoader);
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容