1. 程式人生 > >Spring系列之AOP分析之獲取Advice的過程(四)

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全家桶系列–SpringBootAOP詳解

//本文作者:cuifuan //本文將收錄到選單欄:《Spring全家桶》專欄中 面向方面程式設計(AOP)通過提供另一種思考程式結構的方式來補充面向物件程式設計(OOP)。 OOP中模組化的關鍵單元是類,而在AOP中,模組化單元是方面。 準備工作 首先,使用AOP要在bu

Spring-Cloud-Gateway原始碼分析系列 | Spring-Cloud-GatewayGatewayProperties初始化載入

推薦 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)**:指關注點模組化,這個關注點可能會橫切多個物件。事務