1. 程式人生 > 實用技巧 >Spring AOP面向切面程式設計

Spring AOP面向切面程式設計

一、AOP面向切面程式設計基本概念

在軟體系統中,有些行為對於絕大多數業務模組都是通用,例如日誌管理、許可權管理、事物管理等,在不同的業務模組中,我們很有可能會編寫相同的程式碼來完成一個共同的功能點,這就造成了極大的程式碼冗餘,和較高的維護成本,同時業務程式碼與特殊功能程式碼耦合交融到了一起,不利於系統的構建與開發。

AOP:Aspect Oriented Programming ,面向切面程式設計,就是將眾多的業務模組進行橫向切割,提煉抽取其中的相同功能程式碼進行單獨程式設計,已達到業務程式碼與非業務功能程式碼的隔離,從而使得業務邏輯部分之間的耦合度降低,提高程式的可重用性,同時提高開發效率。

AOP最重要的功能:高內聚,低耦合

二、Spring AOP的基本概念

AOP把軟體系統分成兩個部分:核心關注點和橫切關注點,業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點,描述橫切關注點的具體內容稱之為切面。

描述切面的常用概念是:通知(Advice)切點(Pointcut)連線點(JoinPoint)、目標物件(Target)、織入(Weaving)、代理(Proxy)、切面(aspect)

  • 通知:定義了切面執行的程式碼內容是什麼,在什麼時候執行。
  • 切點:一個或多個連線點的集合,通常使用具體的類名和方法名來指定這些切點,或是使用正則表示式來定義匹配的類和方法來指定這些切點。
  • 連線點:在應用執行過程中能夠插入切面的一個點,這個點可以是呼叫方法時、丟擲異常時、修改一個欄位時,切面程式碼可以利用連線點插入到應用的正常流程之中,並執行切面程式碼。
  • 目標物件:被代理物件。
  • 織入:將通知應用到切入點的過程。
  • 代理:將通知織入到目標物件之後,形成代理物件。
  • 切面:切面是通知和切點的結合,通知和切點共同定義了關於切面的全部內容,切面內容是什麼,在什麼時候執行,在什麼地方執行。(切點+通知)。

Spring中實現AOP原理:

  • 動態代理:被代理物件必須實現接口才能實現代理物件,如果沒有介面將不能使用動態代理技術。

  • cglib代理:第三方的代理技術,可以對任何類生成代理,代理的原理是對目標物件進行繼承代理,如果目標被物件final修飾,那麼該類無法被cglib代理。

  • 如果有介面優先使用動態代理。

Spring AOP中定義了五種型別的通知:

通知型別 描述
Before 再切點方法執行之前,呼叫通知中指定的方法。
After 再切點方法執行完成之後,呼叫通知中指定的方法,不管切點方法執行是否成功。
After-returning 再切點方法成功執行之後,呼叫通知中指定的方法。
After-throwing 再切點方法執行丟擲異常後,呼叫通知中指定的方法。
Around 通知方法包裹切點方法執行,改變切點方法中的執行邏輯

三、Spring AOP程式設計

1. 通過標籤方式進行切面程式設計

<!--切面配置標籤塊-->
<aop:config>
    <!--切點定義,使用正則表示式來匹配連線點集合,通過id來命令切點-->
    <aop:pointcut expression="execution(* com.yingcai.service.*.*(..))" id="pointcut"/>
    <!--通知配置標籤塊,ref屬性定義通知執行Bean-->
    <aop:aspect  ref="adviceInfo">
        <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>
        <aop:after method="afterAdvice" pointcut-ref="pointcut"/>
        <aop:after-throwing method="afterThrowingAdvice" pointcut-ref="pointcut"/>
        <aop:after-returning method="afterReturnAdvice" pointcut-ref="pointcut"/>
        <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>

環繞通知詳解:

通過ProceedingJoinPoin類來獲取操作連線點切入方法的相關資訊

獲取切入方法執行類名稱:

Class executeClass = proceedingJoinPoint.getTarget().getClass();
String className = executeClass.getName();

獲取切入方法名稱:

String methodName = proceedingJoinPoint.getSignature().getName();

獲取切入方法入參:

Object[] args = proceedingJoinPoint.getArgs();

執行切入方法內容:

proceedingJoinPoint.proceed();

注:環繞通知的方法格式必須與連線點方法格式相同,連線點方法有返參,環繞通知方法也必須有返參。

2. 使用註解方式進行切面程式設計

切面註解的開啟:

<aop:aspectj-autoproxy/>
  • @Aspect:標註於類上,將一個類定義為切面類。

  • @Pointcut:標註於一個普通方法上,定義切點內容。

  • @Before:標註於前置通知方法之上。

  • @After:標註於後置方法之上。

  • @AfterThrowing:標註於後置失敗通知方法之上。

  • @AfterReturning:標註於後置成功通知方法之上。

  • @Around:標註於環繞通知方法之上。