AnnotationAwareAspectJAutoProxyCreator職能
AnnotationAwareAspectJAutoProxyCreator是用來處理被@AspectJ注解標(biāo)注的切面類和Spring Advisors的.
其中,Spring Advisors的處理規(guī)則遵循AbstractAdvisorAutoProxyCreator中建立的規(guī)則.
UML

我們從類圖可以看到,AnnotationAwareAspectJAutoProxyCreator的組成結(jié)構(gòu)還是稍微復(fù)雜的。下面我們來過一下其中比較重要的接口.
- AopInfrastructureBean: 實現(xiàn)該接口的類會被標(biāo)記為Spring內(nèi)部的基礎(chǔ)類,Spring AOP并不會對這類型的Bean進(jìn)行代理.
- 與Aware相關(guān)的接口: 通過此類接口獲取容器的BeanFactory和ClassLoader.
-
ProxyConfig: 用于創(chuàng)建代理的配置類,以確保所有代理創(chuàng)建者都具有一致的屬性.內(nèi)部可配置
proxyTargetClass、exposeProxy、optimize等屬性 -
ProxyProcessorSupport: 具有代理處理器通用功能的基類,此外,還特地提供了ClassLoader的管理和
evaluateProxyInterfaces方法,ProxyFactory可以通過evaluateProxyInterfaces方法獲取給定bean類上的接口. - InstantiationAwareBeanPostProcessor: Spring AOP中會在實例化前判斷是否需要創(chuàng)建用戶自定義的代理類,進(jìn)而影響Spring Bean的聲明周期.
- SmartInstantiationAwareBeanPostProcessor: 重量級方法->getEarlyBeanReference,當(dāng)Spring Bean發(fā)生循環(huán)依賴的時候,決定是否要將創(chuàng)建代理的時機(jī)提前.
- BeanPostProcessor: AbstractAutoProxyCreator會在postProcessAfterInitialization中來解析當(dāng)前Bean是否需要代理,正常的Bean是在此處進(jìn)行代理的,當(dāng)執(zhí)行到這步的時候,通常Spring Bean已經(jīng)完成實例化、初始化了。
-
AbstractAutoProxyCreator: 繼承了
ProxyProcessorSupport和SmartInstantiationAwareBeanPostProcessor,是Spring AOP的代理創(chuàng)建器,將匹配代理的地方交由子類去實現(xiàn).同時,它還是getEarlyBeanReference方法的實現(xiàn)者. -
AbstractAdvisorAutoProxyCreator: 提供為每個Bean選擇特定的advisor進(jìn)行代理的功能,提供
findCandidateAdvisors和getAdvicesAndAdvisorsForBean方法用于尋找候選的advisors和為bean匹配advisors. -
AspectJAwareAdvisorAutoProxyCreator: 提供了對advisors進(jìn)行排序的功能,同時為了兼容XML的切面配置解析,也保留了
shouldSkip - AnnotationAwareAspectJAutoProxyCreator: Spring用于解析切面類,將需要執(zhí)行的通知方法轉(zhuǎn)化成Spring Advisor.
Spring Advisor
Spring中的Advisor接口是Spring AOP的基礎(chǔ)接口,一個Advisor可以持有一個pointcut和一個AOP advice.Spring AOP正是通過將被AspectJ標(biāo)注的類中的不同Advice解析成Advisor調(diào)用鏈來執(zhí)行切面邏輯的。
Advised-操作Advisor
public interface Advised extends TargetClassAware {
// 返回當(dāng)前的advised配置是否被凍結(jié)
boolean isFrozen();
// 代理完整的目標(biāo)類而不是指定的接口
boolean isProxyTargetClass();
// 返回由AOP代理代理的接口。
// 將不包括目標(biāo)類別,也可以將其作為代理。
Class<?>[] getProxiedInterfaces();
// 確定是否代理給定的接口
boolean isInterfaceProxied(Class<?> intf);
// 更改此建議對象使用的TargetSource。
// 僅在未凍結(jié)配置的情況下有效。
void setTargetSource(TargetSource targetSource);
// 返回此Advised對象使用的TargetSource。
TargetSource getTargetSource();
// 設(shè)置代理是否應(yīng)由AOP框架公開為ThreadLocal以便通過AopContext類進(jìn)行檢索。
// 默認(rèn)值為false,以實現(xiàn)最佳性能。
void setExposeProxy(boolean exposeProxy);
// 當(dāng)前代理工廠是是否將代理類引用通過ThrealLocal管理起來.
boolean isExposeProxy();
// 獲取當(dāng)前代理的所有advisors
Advisor[] getAdvisors();
// 向當(dāng)前proxy的advisor調(diào)用鏈追加一個advisor
void addAdvisor(Advisor advisor) throws AopConfigException;
// 向當(dāng)前proxy的advisor調(diào)用鏈中的某個位置插入一個advisor
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
// 移除給定的advisor
boolean removeAdvisor(Advisor advisor);
// 移除某個位置中的advisor
void removeAdvisor(int index) throws AopConfigException;
// 獲取當(dāng)前advisor在執(zhí)行鏈中的位置. -1代表沒有任何的advisor
int indexOf(Advisor advisor);
// 替代某個advisor
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
// 向advice的攔截鏈中添加給定的AOP Alliance advice
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
boolean removeAdvice(Advice advice);
int indexOf(Advice advice);
// 返回AOP代理的配置項。
String toProxyConfigString();
}
TargetSource
Spring AOP并不是直接代理目標(biāo)類,而是通過代理TargetSource接口進(jìn)而實現(xiàn)動態(tài)代理.
簡單來說即: Spring AOP->TargetSource->targetObject
- UML

Spring官網(wǎng)對TargerSource的介紹
加載切面類并解析advisor
- AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 從緩存中獲取當(dāng)前BeanClass的Class對象,在advisedBeans這個Map中,以class為key
// 同時,該class還充當(dāng)proxyTypes這個Map中的key
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 如果當(dāng)前類已經(jīng)被動態(tài)代理了,不進(jìn)行任何操作
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 當(dāng)前beanClass是否實現(xiàn)Advice、Pointcut、Advisor、AopInfrastructureBean
// 是否需要跳過解析
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 如果當(dāng)前beanClass存在用戶自定義的TargetSource,則進(jìn)行代理
// 在Spring AOP中,動態(tài)代理并不是直接代理target對象的,而是通過代理TargetSource來間接代理target對象
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 獲取當(dāng)前bean的advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 創(chuàng)建代理類
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
- 需要過濾已經(jīng)創(chuàng)建過動態(tài)代理的類,
advisedBeans這個Map便是緩存已經(jīng)被Spring AOP處理過的BeanClass.- 其中
isInfrastructureClass會過濾掉Spring AOP框架內(nèi)部的基類,同時會識別當(dāng)前是否標(biāo)注了@AspectJ與被ajc編譯器所編譯.- 如果當(dāng)前用戶自定義實現(xiàn)了TargetSource接口,那么AbstractAutoProxyCreator會為用戶自定義的TargetSource創(chuàng)建代理.
我們深入
isInfrastructureClass這個方法看看,step into!
isInfrastructureClass-忽略Spring AOP的基礎(chǔ)服務(wù)類
- org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
父類中的AbstractAutoProxyCreator調(diào)用了AnnotationAwareAspectJAutoProxyCreator中的isInfrastructureClass,這里有2個判斷:
- 調(diào)用父類的
isInfrastructureClass,返回true則直接中斷.
父類執(zhí)行isInfrastructureClass的邏輯為:當(dāng)前beanClass是否實現(xiàn)Advice、Pointcut、Advisor、AopInfrastructureBean. - 判斷當(dāng)前
beanClass是否為切面類.isApsect的邏輯比較簡單:beanClass上是否標(biāo)注了@Aspect注解并且沒有被ajc編譯器編譯過.
- org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect
public boolean isAspect(Class<?> clazz) {
// 類上是否標(biāo)注@Aspect并且沒有被ajc編譯器編譯過
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
shouldSkip-將切面類解析成advisor
- org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 查找候選的advisors
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
shouldSkip是Spring AOP構(gòu)建advisor的入口,spring會在每次執(zhí)行
postProcessBeforeInstantiation的時候,解析每個advisor,解析完成后將advisors進(jìn)行緩存,進(jìn)而判斷當(dāng)前的beanClass和beanName是否已經(jīng)解析完畢. 下面,我們來看看findCandidateAdvisors這個方法做了什么,step into.
- org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 添加根據(jù)超類規(guī)則找到的所有Spring advisors.從層級關(guān)系我們可以知道,
// AspectJAwareAdvisorAutoProxyCreator提供對XML或者實現(xiàn)接口的AOP配置解析
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 注解驅(qū)動的AOP切面解析類解析
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
這里面
findCandidateAdvisors分成了兩條線路:
- 調(diào)用父類
AspectJAwareAdvisorAutoProxyCreator#finCandidateAdvisors提供對XML或者實現(xiàn)接口的AOP配置解析成advisor列表.- 解析注解形式的Aspect成advisor列表.
最后,都添加進(jìn)advisor列表中.
解析advisor類型的bean.
- org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// BeanFactoryAdvisorRetrievalHelperAdapter#findAdvisorBeans
return this.advisorRetrievalHelper.findAdvisorBeans();
}
這里進(jìn)行了一個helper的委托,真正執(zhí)行者為
BeanFactoryAdvisorRetrievalHelperAdapter#findAdvisorBeans.
- org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
/**
* <p>Find all eligible Advisor beans in the current bean factory,
* ignoring FactoryBeans and excluding beans that are currently in creation.</p>
* 在當(dāng)前beanFactory中查找所有有資格的advisor.<br>
* 對FactoryBean和正在創(chuàng)建中的bean不生效 <br>
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
// 從緩存中獲取容器中所有的advisor bean的名字?jǐn)?shù)組
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 如果緩存中沒有,那么從容器中以及其父容器中分析得到所有的advisor bean的名稱
// BeanFactoryUtils.beanNamesForTypeIncludingAncestors此處是找到類型為advisor的bean
// 注意,spring不推薦在此處實例化factoryBeans,因為spring需要保留所有未初始化的常規(guī)類
// 以使自動代理創(chuàng)建者對其應(yīng)用!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 回種緩存
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
// 是否為合適的bean,提供給用戶自定義實現(xiàn),默認(rèn)返回true
if (isEligibleBean(name)) {
// 創(chuàng)建中的bean會被忽略,beanPostProcessor是每次加載bean都會觸發(fā)的鉤子
// 所以在下次進(jìn)來時,可能當(dāng)前正在創(chuàng)建的bean已經(jīng)被創(chuàng)建好了
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 根據(jù)advisorName獲取advisor實例
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
// 省略處理異常細(xì)節(jié)
}
}
}
}
return advisors;
}
首先,會嘗試從緩存中獲取
advisorNames數(shù)組,里面存儲了容器中所有的advisor bean的名字.如果無法從緩存中獲取,那么重新加載符合條件的advisorNames數(shù)組,回種緩存.這里要注意:BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false);中,傳入的是Advisor類型.,也就是尋找類型為Advisor的beanName,并非所有beanName.遍歷
advisorNames數(shù)組,對符合條件的advisor進(jìn)行getBean操作,然后添加進(jìn)advisors集合返回.
buildAspectJAdvisors-解析被@Aspect注解標(biāo)記的類
/**
* Look for AspectJ-annotated aspect beans in the current bean factory,
* and return to a list of Spring AOP Advisors representing them.
* <p>Creates a Spring Advisor for each AspectJ advice method.<br>
* 1. 從容器獲取所有的beanName集合 <br>
* 2. 找到其中被@AspectJ標(biāo)注的類 <br>
* 3. 解析Aspect類,將其轉(zhuǎn)化成advisors <br>
* 4. 將result加入cache中 <br>
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List<Advisor> buildAspectJAdvisors() {
// 獲取所有aspect類的beanName
List<String> aspectNames = this.aspectBeanNames;
// 如果aspectNames為空,那么進(jìn)行加載
if (aspectNames == null) {
// 雙重檢查鎖,防止多線程之間產(chǎn)生并發(fā)訪問
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
// 保存切面名稱的集合
aspectNames = new ArrayList<>();
// 獲取所有的beanName
// BeanFactoryUtils.beanNamesForTypeIncludingAncestors傳入的type為Object
// 也就說查找所有的bean,spring在這里使用了緩存,避免每次加載消耗性能
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 遍歷所有的beanName
for (String beanName : beanNames) {
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,因為在這種情況下,它們將由Spring容器緩存,但不會被編織。
// 獲取bean的類型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.isAspect
// 篩選出當(dāng)前class是否標(biāo)記了@Apsect注解
if (this.advisorFactory.isAspect(beanType)) {
// 將當(dāng)前的beanName加入到aspectNames這個緩存中
aspectNames.add(beanName);
// 獲取當(dāng)前beanClass的aspect元數(shù)據(jù)
// AjType中包含了切面的詳細(xì)數(shù)據(jù)
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// 獲取切面的種類,通常為singleton
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// Aspect中的advice+pointcut可以組成一個個advisor
// 舉個例子,before、after、around每個都會搭配pointcut組成advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 如果bean是單例,存到單例緩存中
this.advisorsCache.put(beanName, classAdvisors);
}
else {
// 否則將工廠和beanName緩存
this.aspectFactoryCache.put(beanName, factory);
}
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;
}
方法比較長,但是總體的脈絡(luò)我們還是可以總結(jié)一下:
- 嘗試從緩存獲取所有的aspectNames集合.如果緩存找不到,重新加載.執(zhí)行的方法又是
BeanFactoryUtils.beanNamesForTypeIncludingAncestors,只不過這次傳入的類型是Object.class,也就是說,獲取的是所有的beanNames.- 遍歷beanNames數(shù)組,通過name獲取type,然后判斷當(dāng)前類是否為Aspect.也就是被
@Aspect注解所標(biāo)記.- 如果是Aspect,構(gòu)建
AspectMetadata,AspectMetadata中保存了AjType,這是AspectJ框架的產(chǎn)物,通過它可以快速獲取當(dāng)前類的pointcut和advice等.Spring AOP正是借助AspectJ來獲取切面類的信息的.此外,AspectJ還提供了很多切面模型種類,通常,我們的切面類都是為singleton-單例.- 調(diào)用
ReflectiveAspectJAdvisorFactory#getAdvisors來解析Aspect類,進(jìn)而解析出List<Advisor>.
- org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 獲取Aspect類的class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 獲取Aspect的類名
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 校驗切面類,不可以為抽象類,需標(biāo)記@Aspect
// spring aop 不支持percflow、percflowbelow種類的aspect
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 使用裝飾器模式包裝MetadataAwareAspectInstanceFactory
// 包裝器類重寫了getAspectInstance方法,并且保證當(dāng)前的factory在使用時才進(jìn)行加載(緩存)
// 正如名字的意義一般 lazy singleton instance
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 獲取aspect切面類中的所有方法,會過濾掉被@Pointcut標(biāo)記的方法
// 獲取到的List<Method>按照Around, Before, After, AfterReturning, AfterThrowing的順序排序
for (Method method : getAdvisorMethods(aspectClass)) {
// 將方法解析成advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
getAdvisors就是我們關(guān)注的注解切面類解析邏輯了:
- 首先從
aspectInstanceFactory中獲取元數(shù)據(jù)進(jìn)而獲取切面類型和切面名稱,隨后對切面類進(jìn)行校驗-切面類不可以為抽象類,需標(biāo)記@Aspect,同時,spring aop 不支持percflow、percflowbelow種類的aspect.- 使用裝飾器模式包裝
MetadataAwareAspectInstanceFactory來懶加載切面類實例.- 獲取當(dāng)前類中標(biāo)記
@Pointcut注解外所有的Method集合,獲取到的List<Method>按照Around,Before,After,AfterReturning,AfterThrowing的順序排序.- 遍歷每一個Method,將符合條件的方法解析成
advisor實例.- 檢查是否有屬于introduction的成員,如果有便進(jìn)行解析(@DeclareParents).
- 將解析完成的每一個advisor添加到返回的結(jié)果集中.
- org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 驗證aspectClass的合法性
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 在切面的方法上構(gòu)建pointcut表達(dá)式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 實例化切面中的advice對象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
- 校驗aspectClass的合法性,這個validate是復(fù)用的,跟上述的方法一致,邏輯就不重復(fù)講了.
- 根據(jù)當(dāng)前的adviceMethod與aspectClass構(gòu)建出AspectJExpressionPointcut實例.它是一個pointcut表達(dá)式的實例.里面對AspectJ框架的表達(dá)式原語進(jìn)行了部分的支持(11種).
- 通過getPointcut()獲取到切點(diǎn)表達(dá)式之后,接下來就可以實例化adivce然后構(gòu)建出advisor了,因為一個advisor = pointcut+advice.我們接著看
InstantiationModelAwarePointcutAdvisorImpl這個方法是如何實例化advice的.
- org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#InstantiationModelAwarePointcutAdvisorImpl
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 當(dāng)前的pointcut表達(dá)式
this.declaredPointcut = declaredPointcut;
// 切面Class
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
// advice方法名稱
this.methodName = aspectJAdviceMethod.getName();
// 方法參數(shù)類型
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
// 方法實例
this.aspectJAdviceMethod = aspectJAdviceMethod;
// aspectJ的advisor工廠
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
// aspectJ實例工廠
this.aspectInstanceFactory = aspectInstanceFactory;
// 切面順序
this.declarationOrder = declarationOrder;
// 切面類名稱
this.aspectName = aspectName;
// 是否需要延時加載
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
// singleton模型的aspect
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 將切面中的advice進(jìn)行實例化
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
InstantiationModelAwarePointcutAdvisorImpl是advisor的子類.在這個構(gòu)造函數(shù)內(nèi)對傳入的屬性進(jìn)行了設(shè)置,然后根據(jù)當(dāng)前的切面模型決定是否需要延遲加載.- 通常我們的切面類都是singleton的,所有會直接執(zhí)行
instantiateAdvice.
- org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
這里直接轉(zhuǎn)發(fā)給了
this.aspectJAdvisorFactory.getAdvice這個方法.繼續(xù)跟蹤.
- org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 獲取切面類Class
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 校驗合法性
validate(candidateAspectClass);
// 獲取切面方法上的注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
// 使用switch來判斷當(dāng)前advice類型
switch (aspectJAnnotation.getAnnotationType()) {
// pointcut不解析
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
// around類型的Advice
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// before類型的Advice
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// after類型的Advice
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
// afterReturning類型的Advice
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
// afterThrowing類型的Advice
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
// 設(shè)置AspectName、DeclarationOrder,為后期執(zhí)行調(diào)用鏈的時候做準(zhǔn)備
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
- 解析Advice之前,Spring又又又對切面類進(jìn)行了一次校驗.
- 解析Advice,根據(jù)當(dāng)前方法上的注解匹配對應(yīng)的advice.例如:around、before、after、afterReturning、afterThrowing.
- 為advice實例配置切面名稱、參數(shù)名稱、聲明順序等.
OK,至此,Advice實例就被解析成功了.此時的
InstantiationModelAwarePointcutAdvisorImpl成員屬性中攜帶了pointcut+advice.
梳理加載Advisors的整體流程.

擴(kuò)展閱讀
【小家Spring】Spring AOP中@Pointcut切入點(diǎn)表達(dá)式最全面使用介紹
【小家Spring】Spring AOP核心類Pointcut解析,對PointcutExpression切點(diǎn)表達(dá)式解析原理分析(以AspectJExpressionPointcut為例)