Spring原始碼-AOP(六)-AOP代理的建立

weixin_34391445發表於2017-09-05

前言

上一篇寫了AspectJAutoProxyBeanDefinitionParser的註冊,以及相關AOP屬性的註冊,接下來看下AspectJAutoProxyBeanDefinitionParser的自動註冊以及它的層級結構。


838913-81e76a8fd21054b8.png

從圖中可以看到AnnotationAwareAspectJAutoProxyCreator實現了BeanPostProcessor,在之前的IOC章節我們之前描述過,Spring載入該bean後會在例項化前呼叫postProcessAfterInitialization()方法,而我們對於AOP邏輯的分析也由此開始。

AOP邏輯分析

【AbstractAutoProxyCreator】

talk is cheap, show you the code:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
    if (bean != null) {
        //根據給定的class和name構建出key,格式:beanClassName_beanName
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            //如果他適合被代理,則需要封裝指定bean
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
protected Object wrapIfNecessary(Object bean, @Nullable String beanName, Object cacheKey) {
    //如果已經處理過就直接返回
    if (beanName != null && 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.
    //如果存在增強方法則建立代理
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //如果獲取了增強則需要針對增強建立代理
    if (specificInterceptors != DO_NOT_PROXY) {
        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;
}

在以上函式中我們已經看到了代理建立的雛形。當然和別的醫院,在開始前先進行一系列的判斷,比如是否已經處理過或者是否需要挑錯,而真正建立代理的程式碼是從getAdvicesAndAdvisorsForBean()開始的。
建立代理前主要包括兩個步驟,如下:

  • 1、獲取增強方法或者增強器
  • 2、根據獲取的增強進行代理
    核心邏輯時序圖如下:
    838913-5943586d06decc48.png

    AbstractAutoProxyCreator的postProcessAfterInitialization() 方法執行時序圖
    雖然看似很簡單,但是每個步驟中都進行了大量的複雜邏輯處理。

AOP設計基礎

這裡再回顧下Spring-AOP的設計基礎

  • 增強(Advice):Advice(也翻作 通知)定義了連線點做什麼,為切面增強提供了織入的介面。在 Spring AOP 中,它主要描述 Spring AOP 圍繞方法呼叫而注入的切面行為。Advice 是 AOP 聯盟定義的一個介面,具體的介面定義在 org.aopalliance.aop.Advice 中。在 Spring AOP 的實現中,使用了這個統一介面,並通過這個介面,為 AOP 切面增強的注入功能做了更多的細化和擴充套件,比如前面提到的具體通知型別,如BeforeAdvice、AfterAdvice、ThrowsAdvice等


    838913-b856040d06447ba1.png
  • 切點:Pointcut(關注點,也稱 切點)用於決定 Advice 增強作用於哪個連線點,也就是說通過 Pointcut 來定義需要增強的方法集合,而這些集合的選取可以通過一定的規則來完成,例如:這些需要增強的地方可以由某個正規表示式來進行標識,或根據某個方法名來進行匹配等。


    838913-fca0def3e9858daf.png
  • 通知器:Advisor(通知器)用一個物件將對目標方法的切面增強設計(Advice)和關注點的設計(Pointcut)結合起來


    838913-bca11a4b78d6d652.png

結束

相應的AOP代理的建立已經結束,下一節開始獲取增強器的分析。

相關文章