AnnotationAwareAspectJAutoProxyCreator職能
AnnotationAwareAspectJAutoProxyCreator
是用來(lái)處理被@AspectJ
注解標(biāo)注的切面類和Spring Advisors
的.
其中,Spring Advisors
的處理規(guī)則遵循AbstractAdvisorAutoProxyCreator
中建立的規(guī)則.
UML
我們從類圖可以看到,AnnotationAwareAspectJAutoProxyCreator
的組成結(jié)構(gòu)還是稍微復(fù)雜的绰垂。下面我們來(lái)過(guò)一下其中比較重要的接口.
- AopInfrastructureBean: 實(shí)現(xiàn)該接口的類會(huì)被標(biāo)記為Spring內(nèi)部的基礎(chǔ)類,Spring AOP并不會(huì)對(duì)這類型的Bean進(jìn)行代理.
- 與Aware相關(guān)的接口: 通過(guò)此類接口獲取容器的BeanFactory和ClassLoader.
-
ProxyConfig: 用于創(chuàng)建代理的配置類链韭,以確保所有代理創(chuàng)建者都具有一致的屬性.內(nèi)部可配置
proxyTargetClass
慎式、exposeProxy
、optimize
等屬性 -
ProxyProcessorSupport: 具有代理處理器通用功能的基類例衍,此外份蝴,還特地提供了ClassLoader的管理和
evaluateProxyInterfaces
方法,ProxyFactory可以通過(guò)evaluateProxyInterfaces
方法獲取給定bean類上的接口. - InstantiationAwareBeanPostProcessor: Spring AOP中會(huì)在實(shí)例化前判斷是否需要?jiǎng)?chuàng)建用戶自定義的代理類驹尼,進(jìn)而影響Spring Bean的聲明周期.
- SmartInstantiationAwareBeanPostProcessor: 重量級(jí)方法->getEarlyBeanReference,當(dāng)Spring Bean發(fā)生循環(huán)依賴的時(shí)候六剥,決定是否要將創(chuàng)建代理的時(shí)機(jī)提前.
- BeanPostProcessor: AbstractAutoProxyCreator會(huì)在postProcessAfterInitialization中來(lái)解析當(dāng)前Bean是否需要代理晚顷,正常的Bean是在此處進(jìn)行代理的,當(dāng)執(zhí)行到這步的時(shí)候疗疟,通常Spring Bean已經(jīng)完成實(shí)例化该默、初始化了。
-
AbstractAutoProxyCreator: 繼承了
ProxyProcessorSupport
和SmartInstantiationAwareBeanPostProcessor
,是Spring AOP的代理創(chuàng)建器策彤,將匹配代理的地方交由子類去實(shí)現(xiàn).同時(shí)栓袖,它還是getEarlyBeanReference
方法的實(shí)現(xiàn)者. -
AbstractAdvisorAutoProxyCreator: 提供為每個(gè)Bean選擇特定的advisor進(jìn)行代理的功能,提供
findCandidateAdvisors
和getAdvicesAndAdvisorsForBean
方法用于尋找候選的advisors和為bean匹配advisors. -
AspectJAwareAdvisorAutoProxyCreator: 提供了對(duì)advisors進(jìn)行排序的功能,同時(shí)為了兼容XML的切面配置解析店诗,也保留了
shouldSkip
- AnnotationAwareAspectJAutoProxyCreator: Spring用于解析切面類,將需要執(zhí)行的通知方法轉(zhuǎn)化成Spring Advisor.
Spring Advisor
Spring中的Advisor接口是Spring AOP的基礎(chǔ)接口裹刮,一個(gè)Advisor可以持有一個(gè)pointcut和一個(gè)AOP advice.Spring AOP正是通過(guò)將被AspectJ
標(biāo)注的類中的不同Advice解析成Advisor調(diào)用鏈來(lái)執(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);
// 更改此建議對(duì)象使用的TargetSource恕洲。
// 僅在未凍結(jié)配置的情況下有效塔橡。
void setTargetSource(TargetSource targetSource);
// 返回此Advised對(duì)象使用的TargetSource梅割。
TargetSource getTargetSource();
// 設(shè)置代理是否應(yīng)由AOP框架公開(kāi)為T(mén)hreadLocal以便通過(guò)AopContext類進(jìn)行檢索霜第。
// 默認(rèn)值為false,以實(shí)現(xiàn)最佳性能户辞。
void setExposeProxy(boolean exposeProxy);
// 當(dāng)前代理工廠是是否將代理類引用通過(guò)ThrealLocal管理起來(lái).
boolean isExposeProxy();
// 獲取當(dāng)前代理的所有advisors
Advisor[] getAdvisors();
// 向當(dāng)前proxy的advisor調(diào)用鏈追加一個(gè)advisor
void addAdvisor(Advisor advisor) throws AopConfigException;
// 向當(dāng)前proxy的advisor調(diào)用鏈中的某個(gè)位置插入一個(gè)advisor
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
// 移除給定的advisor
boolean removeAdvisor(Advisor advisor);
// 移除某個(gè)位置中的advisor
void removeAdvisor(int index) throws AopConfigException;
// 獲取當(dāng)前advisor在執(zhí)行鏈中的位置. -1代表沒(méi)有任何的advisor
int indexOf(Advisor advisor);
// 替代某個(gè)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代理的配置項(xiàng)泌类。
String toProxyConfigString();
}
Spring 官網(wǎng)對(duì)advised接口的描述
TargetSource
Spring AOP并不是直接代理目標(biāo)類,而是通過(guò)代理TargetSource接口進(jìn)而實(shí)現(xiàn)動(dòng)態(tài)代理.
簡(jiǎn)單來(lái)說(shuō)即: Spring AOP->TargetSource->targetObject
- UML
Spring官網(wǎng)對(duì)TargerSource的介紹
加載切面類并解析advisor
- AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 從緩存中獲取當(dāng)前BeanClass的Class對(duì)象,在advisedBeans這個(gè)Map中刃榨,以class為key
// 同時(shí),該class還充當(dāng)proxyTypes這個(gè)Map中的key
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 如果當(dāng)前類已經(jīng)被動(dòng)態(tài)代理了弹砚,不進(jìn)行任何操作
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 當(dāng)前beanClass是否實(shí)現(xiàn)Advice、Pointcut枢希、Advisor桌吃、AopInfrastructureBean
// 是否需要跳過(guò)解析
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 如果當(dāng)前beanClass存在用戶自定義的TargetSource,則進(jìn)行代理
// 在Spring AOP中苞轿,動(dòng)態(tài)代理并不是直接代理target對(duì)象的茅诱,而是通過(guò)代理TargetSource來(lái)間接代理target對(duì)象
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;
}
- 需要過(guò)濾已經(jīng)創(chuàng)建過(guò)動(dòng)態(tài)代理的類,
advisedBeans
這個(gè)Map便是緩存已經(jīng)被Spring AOP處理過(guò)的BeanClass.- 其中
isInfrastructureClass
會(huì)過(guò)濾掉Spring AOP框架內(nèi)部的基類搬卒,同時(shí)會(huì)識(shí)別當(dāng)前是否標(biāo)注了@AspectJ
與被ajc
編譯器所編譯.- 如果當(dāng)前用戶自定義實(shí)現(xiàn)了TargetSource接口,那么AbstractAutoProxyCreator會(huì)為用戶自定義的TargetSource創(chuàng)建代理.
我們深入
isInfrastructureClass
這個(gè)方法看看,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個(gè)判斷:
- 調(diào)用父類的
isInfrastructureClass
,返回true
則直接中斷.
父類執(zhí)行isInfrastructureClass
的邏輯為:當(dāng)前beanClass是否實(shí)現(xiàn)Advice
瑟俭、Pointcut
、Advisor
契邀、AopInfrastructureBean
. - 判斷當(dāng)前
beanClass
是否為切面類.isApsect
的邏輯比較簡(jiǎn)單:beanClass上是否標(biāo)注了@Aspect
注解并且沒(méi)有被ajc
編譯器編譯過(guò).
- org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect
public boolean isAspect(Class<?> clazz) {
// 類上是否標(biāo)注@Aspect并且沒(méi)有被ajc編譯器編譯過(guò)
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會(huì)在每次執(zhí)行
postProcessBeforeInstantiation
的時(shí)候,解析每個(gè)advisor,解析完成后將advisors進(jìn)行緩存坯门,進(jìn)而判斷當(dāng)前的beanClass和beanName是否已經(jīng)解析完畢. 下面微饥,我們來(lái)看看findCandidateAdvisors
這個(gè)方法做了什么,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.從層級(jí)關(guān)系我們可以知道,
// AspectJAwareAdvisorAutoProxyCreator提供對(duì)XML或者實(shí)現(xiàn)接口的AOP配置解析
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 注解驅(qū)動(dòng)的AOP切面解析類解析
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
這里面
findCandidateAdvisors
分成了兩條線路:
- 調(diào)用父類
AspectJAwareAdvisorAutoProxyCreator#finCandidateAdvisors
提供對(duì)XML或者實(shí)現(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)行了一個(gè)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>
* 對(duì)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!
// 如果緩存中沒(méi)有,那么從容器中以及其父容器中分析得到所有的advisor bean的名稱
// BeanFactoryUtils.beanNamesForTypeIncludingAncestors此處是找到類型為advisor的bean
// 注意,spring不推薦在此處實(shí)例化factoryBeans,因?yàn)閟pring需要保留所有未初始化的常規(guī)類
// 以使自動(dòng)代理創(chuàng)建者對(duì)其應(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,提供給用戶自定義實(shí)現(xiàn),默認(rèn)返回true
if (isEligibleBean(name)) {
// 創(chuàng)建中的bean會(huì)被忽略简软,beanPostProcessor是每次加載bean都會(huì)觸發(fā)的鉤子
// 所以在下次進(jìn)來(lái)時(shí),可能當(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實(shí)例
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
// 省略處理異常細(xì)節(jié)
}
}
}
}
return advisors;
}
首先述暂,會(huì)嘗試從緩存中獲取
advisorNames
數(shù)組痹升,里面存儲(chǔ)了容器中所有的advisor bean的名字.如果無(wú)法從緩存中獲取,那么重新加載符合條件的advisorNames
數(shù)組,回種緩存.這里要注意:BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false);
中畦韭,傳入的是Advisor
類型.,也就是尋找類型為Advisor
的beanName疼蛾,并非所有beanName.遍歷
advisorNames
數(shù)組,對(duì)符合條件的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ā)訪問(wèn)
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
// 保存切面名稱的集合
aspectNames = new ArrayList<>();
// 獲取所有的beanName
// BeanFactoryUtils.beanNamesForTypeIncludingAncestors傳入的type為Object
// 也就說(shuō)查找所有的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.
// 必須小心,不要急于實(shí)例化bean赠法,因?yàn)樵谶@種情況下麦轰,它們將由Spring容器緩存,但不會(huì)被編織。
// 獲取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這個(gè)緩存中
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可以組成一個(gè)個(gè)advisor
// 舉個(gè)例子款侵,before末荐、after、around每個(gè)都會(huì)搭配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;
}
方法比較長(zhǎng)甲脏,但是總體的脈絡(luò)我們還是可以總結(jié)一下:
- 嘗試從緩存獲取所有的aspectNames集合.如果緩存找不到,重新加載.執(zhí)行的方法又是
BeanFactoryUtils.beanNamesForTypeIncludingAncestors
妹笆,只不過(guò)這次傳入的類型是Object.class
,也就是說(shuō)剃幌,獲取的是所有的beanNames.- 遍歷beanNames數(shù)組,通過(guò)name獲取type,然后判斷當(dāng)前類是否為Aspect.也就是被
@Aspect
注解所標(biāo)記.- 如果是Aspect,構(gòu)建
AspectMetadata
,AspectMetadata
中保存了AjType
,這是AspectJ
框架的產(chǎn)物晾浴,通過(guò)它可以快速獲取當(dāng)前類的pointcut
和advice
等.Spring AOP正是借助AspectJ來(lái)獲取切面類的信息的.此外负乡,AspectJ還提供了很多切面模型種類,通常脊凰,我們的切面類都是為singleton
-單例.- 調(diào)用
ReflectiveAspectJAdvisorFactory#getAdvisors
來(lái)解析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();
// 校驗(yàn)切面類,不可以為抽象類,需標(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
// 包裝器類重寫(xiě)了getAspectInstance方法,并且保證當(dāng)前的factory在使用時(shí)才進(jìn)行加載(緩存)
// 正如名字的意義一般 lazy singleton instance
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 獲取aspect切面類中的所有方法,會(huì)過(guò)濾掉被@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)而獲取切面類型和切面名稱,隨后對(duì)切面類進(jìn)行校驗(yàn)-切面類不可以為抽象類,需標(biāo)記@Aspect,同時(shí),spring aop 不支持percflow狸涌、percflowbelow種類的aspect.- 使用裝飾器模式包裝
MetadataAwareAspectInstanceFactory
來(lái)懶加載切面類實(shí)例.- 獲取當(dāng)前類中標(biāo)記
@Pointcut
注解外所有的Method集合切省,獲取到的List<Method>按照Around
,Before
,After
,AfterReturning
,AfterThrowing
的順序排序.- 遍歷每一個(gè)Method,將符合條件的方法解析成
advisor
實(shí)例.- 檢查是否有屬于introduction的成員,如果有便進(jìn)行解析(@DeclareParents).
- 將解析完成的每一個(gè)advisor添加到返回的結(jié)果集中.
- org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
// 驗(yàn)證aspectClass的合法性
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 在切面的方法上構(gòu)建pointcut表達(dá)式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 實(shí)例化切面中的advice對(duì)象
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
- 校驗(yàn)aspectClass的合法性帕胆,這個(gè)validate是復(fù)用的朝捆,跟上述的方法一致,邏輯就不重復(fù)講了.
- 根據(jù)當(dāng)前的adviceMethod與aspectClass構(gòu)建出AspectJExpressionPointcut實(shí)例.它是一個(gè)pointcut表達(dá)式的實(shí)例.里面對(duì)AspectJ框架的表達(dá)式原語(yǔ)進(jìn)行了部分的支持(11種).
- 通過(guò)getPointcut()獲取到切點(diǎn)表達(dá)式之后,接下來(lái)就可以實(shí)例化adivce然后構(gòu)建出advisor了懒豹,因?yàn)橐粋€(gè)advisor = pointcut+advice.我們接著看
InstantiationModelAwarePointcutAdvisorImpl
這個(gè)方法是如何實(shí)例化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();
// 方法實(shí)例
this.aspectJAdviceMethod = aspectJAdviceMethod;
// aspectJ的advisor工廠
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
// aspectJ實(shí)例工廠
this.aspectInstanceFactory = aspectInstanceFactory;
// 切面順序
this.declarationOrder = declarationOrder;
// 切面類名稱
this.aspectName = aspectName;
// 是否需要延時(shí)加載
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)行實(shí)例化
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
InstantiationModelAwarePointcutAdvisorImpl
是advisor的子類.在這個(gè)構(gòu)造函數(shù)內(nèi)對(duì)傳入的屬性進(jìn)行了設(shè)置芙盘,然后根據(jù)當(dāng)前的切面模型決定是否需要延遲加載.- 通常我們的切面類都是singleton的,所有會(huì)直接執(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
這個(gè)方法.繼續(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();
// 校驗(yàn)合法性
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來(lái)判斷當(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)用鏈的時(shí)候做準(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又又又對(duì)切面類進(jìn)行了一次校驗(yàn).
- 解析Advice,根據(jù)當(dāng)前方法上的注解匹配對(duì)應(yīng)的advice.例如:around记餐、before驮樊、after、afterReturning片酝、afterThrowing.
- 為advice實(shí)例配置切面名稱囚衔、參數(shù)名稱、聲明順序等.
OK雕沿,至此练湿,Advice實(shí)例就被解析成功了.此時(shí)的
InstantiationModelAwarePointcutAdvisorImpl
成員屬性中攜帶了pointcut+advice.
梳理加載Advisors的整體流程.
擴(kuò)展閱讀
【小家Spring】Spring AOP中@Pointcut切入點(diǎn)表達(dá)式最全面使用介紹
【小家Spring】Spring AOP核心類Pointcut解析,對(duì)PointcutExpression切點(diǎn)表達(dá)式解析原理分析(以AspectJExpressionPointcut為例)