??基于最新Spring 5.x,詳細介紹了DefaultAdvisorAutoProxyCreator的實作原理!
文章目錄
- Spring AOP原始碼 系列文章
- DefaultAdvisorAutoProxyCreator原理
Spring AOP原始碼 系列文章
Spring AOP原始碼(1)—<aop:config/>AOP配置標簽決議
Spring AOP原始碼(2)—AspectJAwareAdvisorAutoProxyCreator創建代理物件
Spring AOP原始碼(3)—invoke代理方法的呼叫與執行增強
Spring AOP原始碼(4)—基于注解的AOP原始碼決議以及AnnotationAwareAspectJAutoProxyCreator
Spring AOP原始碼(5)—DefaultAdvisorAutoProxyCreator自動代理創建者
DefaultAdvisorAutoProxyCreator原理
??此前,我們已經講解了AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator的原始碼,它們是最普通(普遍的)Spring AOP的實作原理,因此是最重要的,如果具有<aop:config/>標簽,那么默認使用AspectJAwareAdvisorAutoProxyCreator來創建代理,如果具有<aop:aspectj-autoproxy/>標簽或者@EnableAspectJAutoProxy注解,那么默認使用AnnotationAwareAspectJAutoProxyCreator來創建代理,
??DefaultAdvisorAutoProxyCreator同樣繼承了AbstractAdvisorAutoProxyCreator,是四種基于Advisor的自動代理創建者的實作之一:

??DefaultAdvisorAutoProxyCreator使用的地方實際上并不是很多,在我們了解了AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator的原始碼之后,我們知道Spring AOP的大部分處理流程都是在父類AbstractAutoProxyCreator和AbstractAdvisorAutoProxyCreator中完成的,這些具體的實作類僅僅是重寫了某些方法來實作自己的特性,因此DefaultAdvisorAutoProxyCreator的原理也非常的簡單!
??DefaultAdvisorAutoProxyCreator和前兩個AutoProxyCreator的大概區別如下:
sortAdvisors:用于對已找到的Advisors鏈進行排序,- DefaultAdvisorAutoProxyCreator采用父類AbstractAdvisorAutoProxyCreator的默認sortAdvisors方,基于AnnotationAwareOrderComparator比較器的排序,
- 另兩個AutoProxyCreator則重寫了該方法,除了使用AnnotationAwareOrderComparator之外,還是用了aspectName、declarationOrder(宣告順序)來進行排序!
extendAdvisors:用于對已找到的Advisors鏈進行擴展,- DefaultAdvisorAutoProxyCreator采用父類AbstractAdvisorAutoProxyCreator的默認extendAdvisors方法,該方法中什么也沒做,
- 另兩個AutoProxyCreator則重寫了該方法,并且在Advisors鏈的頭部添加一個特殊的Advisor——DefaultPointcutAdvisor,其內部的ExposeInvocationInterceptor用于暴露MethodInvocation,
shouldSkip:判斷是否需要跳過對給定bean進行的自動代理,- DefaultAdvisorAutoProxyCreator采用父類AbstractAutoProxyCreator的默認shouldSkip方法,邏輯是:如果beanName以beanCassName開頭,并且以“.ORIGINAL”結束,那么回傳true,表示當前bean應該采用原始實體,禁止代理,否則回傳false,
- 另兩個AutoProxyCreator則重寫了該方法,將會通過findCandidateAdvisors方法查找beanFactory中的所有Advisor型別的通知器bean定義并且初始化(這個方法在其他地方也會呼叫),如果存在AspectJPointcutAdvisor型別的通知器實體,并且beanName等于aspectName,即表示當前的bean屬于這個通知器的切面方法類bean,那么不應該攔截切面方法類的方法,直接回傳true,表示跳過,否則在最后會才會呼叫父類的邏輯,
isEligibleAdvisorBean:在findAdvisorBeans(查找候選Advisors)方法中,根據通知器的beanName判斷通知器bean是否是合格的候選通知器,- 另兩個AutoProxyCreator使用了父類AbstractAdvisorAutoProxyCreator的邏輯,默認始侄訓傳true,也就是不根據名稱篩選,
- DefaultAdvisorAutoProxyCreator則重寫了該方法,支持beanName具有給定前綴的通知器bean才能夠算作候選Advisor通知器,這也是DefaultAdvisorAutoProxyCreator最大的功能點和特點,是我們下面重點學習的地方!
??DefaultAdvisorAutoProxyCreator支持beanName具有給定前綴的通知器bean才能夠算作候選Advisor通知器,它提供了advisorBeanNamePrefix屬性用來手動設定前綴:
@Nullable
private String advisorBeanNamePrefix;
/**
* 設定Advisor通知器 beanName 的前綴
*/
public void setAdvisorBeanNamePrefix(@Nullable String advisorBeanNamePrefix) {
this.advisorBeanNamePrefix = advisorBeanNamePrefix;
}
/**
* 獲取Advisor通知器 beanName 的前綴
*/
@Nullable
public String getAdvisorBeanNamePrefix() {
return this.advisorBeanNamePrefix;
}
??DefaultAdvisorAutoProxyCreator還實作了BeanNameAware介面,容器中的DefaultAdvisorAutoProxyCreator在實體化完畢之后的initializeBean初始化方法中,首先就會呼叫BeanNameAware介面的setBeanName方法,并將當前DefaultAdvisorAutoProxyCreator的beanName傳遞到方法引數中!
??DefaultAdvisorAutoProxyCreator的setBeanName方法實作如下,它的目的就是在沒有配置advisorBeanNamePrefix的時候,設定默認的前綴為beanName+".",
/**
* 默認的前綴的點
*/
public static final String SEPARATOR = ".";
/**
* bean實體創建完畢之后自動回呼的方法,將當前創建的bean的beanName傳遞進來
*
*/
@Override
public void setBeanName(String name) {
//如果未設定Advisor通知器 beanName 的前綴,那么使用beanName+"."作為默認前綴
if (this.advisorBeanNamePrefix == null) {
this.advisorBeanNamePrefix = name + SEPARATOR;
}
}
??當然,我們也可以通過usePrefix屬性手動控制是否開啟前綴匹配,默認不啟用,即所有的Advisor都是候選Advisor,
/**
* 是否啟用前綴匹配的標志,默認不啟用,即所有的Advisor都是候選Advisor
*/
private boolean usePrefix = false;
/**
* 設定啟用標志
*/
public void setUsePrefix(boolean usePrefix) {
this.usePrefix = usePrefix;
}
/**
* 獲取啟用標志
*/
public boolean isUsePrefix() {
return this.usePrefix;
}
??最后就是我們的isEligibleAdvisorBean方法了,它也非常的簡單,用于判斷是否是合格的候選AdvisorBean,如果啟用前綴匹配,那么通過beanName匹配前綴,否則默認回傳true,
/**
* 判斷是否是合格的候選AdvisorBean
* <p>
* 如果啟用前綴匹配,那么beanName匹配前綴,否則默認回傳true
*
* @param beanName 某個Advisor的beanName
*/
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
//如果沒有啟用前綴匹配,那么直接回傳true,表示合格
if (!isUsePrefix()) {
return true;
}
//那么如果prefix不為null并且當前Advisor的beanName以指定的前綴開始,那么說明合格,否則回傳false
String prefix = getAdvisorBeanNamePrefix();
return (prefix != null && beanName.startsWith(prefix));
}
??是的,DefaultAdvisorAutoProxyCreator介紹完了,它就是這么簡單……當然這里的“簡單”是建立在我們已經熟悉了至少是AspectJAwareAdvisorAutoProxyCreator自動代理創建者的原始碼之后,而AspectJAwareAdvisorAutoProxyCreator的原始碼我們此前就講過了!
如有需要交流,或者文章有誤,請直接留言,另外希望點贊、收藏、關注,我將不間斷更新各種Java學習博客!
CSDN認證博客專家
Javaer
博客專家
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260567.html
標籤:java
