1. 程式人生 > 程式設計 >SpringAOP切點函式實現原理詳解

SpringAOP切點函式實現原理詳解

一:在函式入參中使用萬用字元

@AspectJ支援3種萬用字元

* :匹配任意字元,但它只能匹配上下文中的一個元素.

.. :匹配任意字元,可以匹配上下文中多個元素,但在表示類時,必須和*聯合使用,而在表示入參時則單獨使用

+ :表示按型別匹配指定類的所有類,必須跟在類名後面,如com.smart.Car+ ;繼承或擴充套件指定類的所有類,同時還包括指定類本身.

@AspectJ函式按其是否支援萬用字元及支援的程度,可以分為以下3類.

1):支援所有的萬用字元:execution(),within()

2):僅支援“+”萬用字元:args(),this(),target()

3):不支援萬用字元:@args(),within(),target();@annotation()

此外,args(),target(),@args(),@within(),@target()和@annotation()這7個函式除了可以指定類名外,也可以指定變數名,並將目標物件中的變數繫結到增強的方法中.

二:切點函式詳解

[1]:@annotation()

@annotation()表示標註了某個註解的所有方法.

eg:

package com.springboot.test;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TestAspect {
  @AfterReturning("@annotation(com.springboot.anno.NeedTest)")
  public void needTestFun() {
    System.out.println("needTestFun() executed!");
  }
}

[2]:execution()

execution()是最常用的切點函式,其語法如下:

execution(<修飾符模式>?<返回型別模式><方法名模式>(<引數模式>) <異常模式>?)

除了返回型別模式,方法名模式,引數模式外,其他項都是可選的.

  (1):通過方法簽名定義切點

  execution(public * *(..)):匹配所有目標類的public方法,第一個*代表返回型別,第二個*代表方法名,而..代表任意入參的方法.

  execution(* *To(..)):匹配所有以To為字尾的方法,而*To代表任意以To為字尾的方法.

  (2):通過類定義切點

  execution(* com.springboot.Waiter.*(..)):匹配Waiter介面的所有方法,第一個*代表返回任意型別;com.springboot.Waiter.*(..)代表Waiter介面的所有方法,

  (3):通過類包定義切點

  在類名模式串中,“.*”表示包下所有的類,而“..*”表示包,子孫包下的所有類.

  execution(* com.smart.*(..)):匹配com.smart包下的所有類的所有方法.

  execution(* com.smart..*(..)):匹配com.smart包.子孫包下所有的類的所有方法.

  execution(* com..*.*Dao.find*(..)):匹配包名字首為com的任何包下類名字尾為Dao的方法,方法名必須以find為字首.如:com.smart.UserDao#findByUserId(),  com.smart.dao.ForumDao#findById()等.

  (4):通過方法入參定義切點:

  切點表示式中的方法入參部分比較複雜,可以使用“*”,“..”萬用字元.其中“*”表示任意型別的引數;而“..”表示任意型別的引數且引數個數不限.

  execution(* joke(String,int)):匹配joke(String str,int d)方法.

  execution(* joke(String,*):匹配目標類中的joke(),但該方法的第一個入參為String型別,第二個入參可以是任意型別.

  execution(* joke(String,..)):匹配目標類中的joke(),該方法的第一個入參為String型別,後面可以有任意個入參,且入參型別不受限制.

  execution(* joke(Object+)):匹配目標類中的joke(),方法擁有一個入參,且入參是Object型別或該類的子類.

[3]:args()和@args()

args():該函式接收一個類名,表示目標類方法入參物件是指定類(包含字類)時,切點匹配

  1):args(com.smart.Waiter)表示執行時入參是Waiter型別的方法,其等價於execution(* *(com.smart.Waiter+))當然也等價於args(com.smart.Waiter+).

  2):@args() 太囉嗦,不打字了...

[4]:within()

通過類匹配模式串宣告切點,within()函式定義的連線點是針對目標類而言的,而非針對執行期物件的型別而言,這一點和execution()是相同的.但和execution()函式不同的是,within()所指定的連線點的最小範圍只能是類,二execution()所指定的連線點可以大到包,小到方法入參.所以從某種意義上說,execution()函式的功能涵蓋了within()函式的功能.within()函式語法如下:

within(<類匹配模式>)

  •   within(com.smart.NativeWaiter): 匹配目標類NativeWaiter的所有方法.
  •   within(com.smart.*):  匹配com.smart包中的所有類,但不包括子孫包,所以com.smart.service包中類的方法不匹配這個切點
  •   within(co.smart..*):  匹配com.smart包及子孫包中的類,所以com.smart.service,com.smart.dao,com.smart.service.forum等包中的所有類都匹配這個切點.

[5]@within(),@target()

[6]target(),this()

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。