前言
上一篇寫了AspectJAutoProxyBeanDefinitionParser的注冊,以及相關AOP屬性的注冊,接下來看下AspectJAutoProxyBeanDefinitionParser的自動注冊以及它的層級結構。
從圖中可以看到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、根據獲取的增強進行代理
核心邏輯時序圖如下:
AbstractAutoProxyCreator的postProcessAfterInitialization() 方法執行時序圖
雖然看似很簡單,但是每個步驟中都進行了大量的復雜邏輯處理。
AOP設計基礎
這里再回顧下Spring-AOP的設計基礎
-
增強(Advice):Advice(也翻作 通知)定義了連接點做什么,為切面增強提供了織入的接口。在 Spring AOP 中,它主要描述 Spring AOP 圍繞方法調用而注入的切面行為。Advice 是 AOP 聯盟定義的一個接口,具體的接口定義在 org.aopalliance.aop.Advice 中。在 Spring AOP 的實現中,使用了這個統一接口,并通過這個接口,為 AOP 切面增強的注入功能做了更多的細化和擴展,比如前面提到的具體通知類型,如BeforeAdvice、AfterAdvice、ThrowsAdvice等
-
切點:Pointcut(關注點,也稱 切點)用于決定 Advice 增強作用于哪個連接點,也就是說通過 Pointcut 來定義需要增強的方法集合,而這些集合的選取可以通過一定的規則來完成,例如:這些需要增強的地方可以由某個正則表達式來進行標識,或根據某個方法名來進行匹配等。
-
通知器:Advisor(通知器)用一個對象將對目標方法的切面增強設計(Advice)和關注點的設計(Pointcut)結合起來
結束
相應的AOP代理的創建已經結束,下一節開始獲取增強器的分析。