Spring系列之AOP分析之獲取Advice的過程(四)
我們在前面的文章中分析了從切面類中獲取Advisor的過程,我們最後建立的Advisor例項為:InstantiationModelAwarePointcutAdvisorImpl,它是一個Advisor和PointcutAdvisor的實現類,所以我們可以從這個類中獲取Advice和Pointcut。從之前的分析中我們也看到了Pointcut的賦值,在這一篇文章中我們將會具體分析Advice的建立過程。
我們在上一篇文章的末尾說到了這一段程式碼可以例項化Advice。我們來看看這個方法的程式碼:
this.instantiatedAdvice = instantiateAdvice(this .declaredPointcut);
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
//入參為切點表示式類
//這裡是通過呼叫aspectJAdvisorFactory來獲取Advice
//aspectJAdvisorFactory的例項是ReflectiveAspectJAdvisorFactory所以最終我們還是要到
//ReflectiveAspectJAdvisorFactory中去分析Advice的獲取過程
//ReflectiveAspectJAdvisorFactory真是一個重要的類啊Advisor和Advice的獲取都是在這個類中完成的
//入參為:通知方法、切點表示式類、切面例項、切面的一個順序、切面類名
//倒騰了倒騰去基本上還是這幾個引數
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
ReflectiveAspectJAdvisorFactory中getAdvice方法的程式碼如下
public Advice getAdvice (Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//切面類 帶有@Aspect註解的類
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
//驗證切面類 不再分析了
validate(candidateAspectClass);
//又來一遍 根據通知方法 獲取通知註解相關資訊
//在獲取Advisor的方法 我們已經見過這個呼叫。這個在Spring的AnnotationUtils中會快取方法的註解資訊
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//再去校驗一遍 如果不是切面類 則丟擲異常
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
AbstractAspectJAdvice springAdvice;
//在上一篇文章的分析中 我們說過在AspectJAnnotation中會存放通知型別
switch (aspectJAnnotation.getAnnotationType()) {
//如果是前置通知,則直接建立AspectJMethodBeforeAdvice例項
//入參為:通知方法、切點表示式、切面例項
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是後置通知,則直接建立AspectJAfterAdvice例項
//入參為:通知方法、切點表示式、切面例項
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是後置返回通知,則直接建立AspectJAfterReturningAdvice例項
//入參為:通知方法、切點表示式、切面例項
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
//設定後置返回值的引數name
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
//如果是後置異常通知,則直接建立AspectJAfterThrowingAdvice例項
//入參為:通知方法、切點表示式、切面例項
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
//設定後置異常通知 異常型別引數name
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
//如果是後置異常通知,則直接建立AspectJAfterThrowingAdvice例項
//入參為:通知方法、切點表示式、切面例項
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//如果是切點方法,則什麼也不做
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
//上面的那幾種情況都不是的話,則丟擲異常
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
//切面的名字
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
//通知註解中的引數名
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
//引數繫結
springAdvice.calculateArgumentBindings();
return springAdvice;
}
上面即是獲取Advice的過程。我們簡單的看一下calculateArgumentBindings這個方法做了什麼事:
calculateArgumentBindings
public synchronized final void calculateArgumentBindings() {
//如果已經進行過引數綁定了 或者通知方法中沒有引數
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
return;
}
int numUnboundArgs = this.parameterTypes.length;
//通知方法引數型別
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
//如果第一個引數是JoinPoint或者ProceedingJoinPoint
if (maybeBindJoinPoint(parameterTypes[0]) ||
//這個方法中還有一個校驗 即只有在環繞通知中第一個引數型別才能是ProceedingJoinPoint
maybeBindProceedingJoinPoint(parameterTypes[0])) {
numUnboundArgs--;
}
//如果第一個引數是JoinPoint.StaticPart
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
numUnboundArgs--;
}
if (numUnboundArgs > 0) {
//進行引數繫結 繫結過程略複雜
//常見的場景是我們使用 後置返回通知和後置異常通知的時候 需要指定 returning和throwing的值
bindArgumentsByName(numUnboundArgs);
}
this.argumentsIntrospected = true;
}
通過前面的分析我們可以瞭解到一個切面中的通知方法會生成一個Advisor例項(如InstantiationModelAwarePointcutAdvisorImpl,其實這個也是我們在SpringAOP中最常用的一個Advisor實現類),在生成這個Advisor例項的過程中會建立一個相應的Advice例項! 一個通知方法—->一個Advisor(包含Pointcut)——>一個Advice!
PS:這裡只是一個生成Advice的地方,在其他的地方也會生成Advice,我們在以後再分析。
相關推薦
Spring系列之AOP分析之獲取Advice的過程(四)
我們在前面的文章中分析了從切面類中獲取Advisor的過程,我們最後建立的Advisor例項為:InstantiationModelAwarePointcutAdvisorImpl,它是一個Advisor和PointcutAdvisor的實現類,所以我們可以從這
Spring系列之AOP分析之對通知方法的執行過程(九)
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80261327 我們在上一篇文章中說到了前置通知的方法呼叫AspectJMethodBeforeAdvice#before,在這個before方法中又呼叫
Spring Ioc 源碼分析之Bean的加載和構造
!= tel string ebean cti name wired resource 事情 我們都知道,Spring Ioc和Aop是Spring的核心的功能,因此花一點時間去研究還是很有意義的,如果僅僅是知其所以然,也就體會不到大師設計Spring的精華,還記得那句話,
Java併發系列 | AbstractQueuedSynchronizer原始碼分析之概要分析
學習Java併發程式設計不得不去了解一下java.util.concurrent這個包,這個包下面有許多我們經常用到的併發工具類,例如:ReentrantLock, CountDownLatch, CyclicBarrier, Semaphore等。而這些類的底層實現都依賴於AbstractQueu
Spring框架的AOP技術之通知型別
1. 通知型別 * @Before -- 前置通知 * @AfterReturing -- 後置通知 * @Around -- 環繞通知(目標物件方法預設不執行的,需要手動執行) * @After
Service Mesh深度學習系列|istio原始碼分析之pilot
本文分析的istio程式碼版本為0.8.0,commit為0cd8d67,commit時間為2018年6月18日。 上面是官方關於pilot的架構圖,因為是old_pilot_repo目錄下,可能與最新架構有出入,僅供參考。所謂的pilot包含兩個元件:pilot-agent和pilot-d
Kafka原始碼之KafkaConsumer分析之offset操作
當消費者正常消費過程中以及Rebalance操作開始之前,都會提交一次Offset記錄Consumer當前的消費位置。在SubscriptionState中使用TopicPartitionState記錄了每個TopicPartition的消費狀況,TopicPa
Spring系列之AOP
-a cte implement 結合 動態擴展 分離 可操作性 技術 其中 一、什麽是AOPAOP(Aspect-OrientedProgramming,面向方面編程),可以說是OOP(Object-Oriented Programing,面向對象編程)的補充和完善。OO
Spring系列之AOP實現的兩種方式
部分 靜態常量 cep value conf tar import enc ble AOP常用的實現方式有兩種,一種是采用聲明的方式來實現(基於XML),一種是采用註解的方式來實現(基於AspectJ)。 首先復習下AOP中一些比較重要的概念: Joinpoint(連接點)
Spring全家桶系列–SpringBoot之AOP詳解
//本文作者:cuifuan //本文將收錄到選單欄:《Spring全家桶》專欄中 面向方面程式設計(AOP)通過提供另一種思考程式結構的方式來補充面向物件程式設計(OOP)。 OOP中模組化的關鍵單元是類,而在AOP中,模組化單元是方面。 準備工作 首先,使用AOP要在bu
Spring-Cloud-Gateway原始碼分析系列 | Spring-Cloud-Gateway之GatewayProperties初始化載入
推薦 Spring Boot/Cloud 視訊: 在Spring-Cloud-Gateway初始化時我們在GatewayAutoConfiguration配置中看到了有初始化載入GatewayProperties例項的配置,接下來學習下GatewayPrope
Spring系列之AOP的原理及手動實現
目錄 Spring系列之IOC的原理及手動實現 Spring系列之DI的原理及手動實現 引入 到目前為止,我們已經完成了簡易的IOC和DI的功能,雖然相比如Spring來說肯定是非常簡陋的,但是畢竟我們是為了理解原理的,也沒必要一定要做一個和Spring一樣的東西。到了現在並不能讓我們鬆一
Spring原始碼分析之ProxyFactoryBean方式實現Aop功能的分析
實現Aop功能有兩種方式, 1. ProxyFactoryBean方式: 這種方式是通過配置實現 2. ProxyFactory方式:這種方式是通過程式設計實現 這裡只說ProxyFactoryBean方式 首先說下具體的配置,一個例子如下: <bean id="t
Spring系列之Spring框架和SpringAOP整合過程分析(十二)
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80808447 在這篇文章中我們接著上一篇的文章說。在上一篇文章中我們提到了getAdvicesAndAdvisorsForBean這個方法,這個方法的內
Spring系列之Spring框架和SpringAOP整合過程分析(十)
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80724180 在開始這個系列之前大家先想一下我們是怎麼在專案中使用SpringAOP的(這裡的分析都是基於AspectJ註解的)。我們需要在我們的Spr
Spring系列之AOP基本主要類概述
在這篇文章中我將對自己瞭解的AOP中的基本主要類做一個概述,可能不包括一些AOP高階用法的類以及是自己還不瞭解的類。會不定期的進行補充和修改。 SpringAOP基礎解析類 類名 作用
Spring系列之六:AOP的代理詳解
Aop是面向切片的程式設計,首先先用圖解釋AOP的程式設計這是沒有用aop的情況,程式碼中存在大量的重複的程式碼:使用aop就是採用一個切片,對封裝好的程式進行切開,減少重複的程式碼,對重複的程式碼進行復用:那麼如何實現這種aop的切片程式設計了?就是使用動態代理的方式,為方
Spring系列之——Spring事務以及兩大核心IOC和AOP
配置 一起 ans 事務 控制反轉 系列 成功 ger manager 1 Spring事務 1.1 Spring事務是什麽(百度) 事務是對一系列的數據庫操作(比如插入多條數據)進行統一的提交或是回滾操作,如果插入成功,那麽一起成功,如果中間一條出現異常,那麽回滾
Spring系列之aAOP AOP是什麼?+xml方式實現aop+註解方式實現aop
## Spring系列之aop aop是什麼?+xml方式實現aop+註解方式實現aop ## 什麼是AOP? AOP為Aspect Oriented Programming 的縮寫,意識為面向切面的程式設計,是通過**預編譯**和**執行期動態代理**實現程式功能的統一維護的一種技術 AOP是OOP(Ob
Spring原始碼分析之AOP從解析到呼叫
正文: 在上一篇,我們對IOC核心部分流程已經分析完畢,相信小夥伴們有所收穫,從這一篇開始,我們將會踏上新的旅程,即Spring的另一核心:AOP! 首先,為了讓大家能更有效的理解AOP,先帶大家過一下AOP中的術語: - **切面(Aspect)**:指關注點模組化,這個關注點可能會橫切多個物件。事務