Spring切點表達式
一、概要
前面定義切點表達式時使用了execution表達式,其實execution就是一個切入點指示符。Spring AOP僅支持部分AspectJ的切入點指示,但基本已經(jīng)滿足我們大部分的需求了,同時Spring AOP還額外支持一個bean切入點指示符。
切面表達式主要由:designators(指示器,匹配java方法),wildcards(通配符),operators(操作運算符)三部分組成
二、指示器
1、說明
主要作用就是通過什么樣的方式來匹配java類的哪些方法
2、分類
按著作用來分主要分為 匹配方法(execution),匹配注解(@within,@target,@args,@annotation),匹配包/類型(within()),匹配對象(target,this),匹配參數(shù)(args)
3、支持的指示器
| 指示器 | 描述 |
|---|---|
| execution() | 用于匹配方法執(zhí)行的連接點 |
| within() | 用于匹配指定的類及其子類中的所有方法 |
| this() | 匹配可以向上轉(zhuǎn)型為this指定的類型的代理對象中的所有方法 |
| target() | 匹配可以向上轉(zhuǎn)型為target指定的類型的目標對象中的所有方法 |
| args() | 用于匹配運行時傳入的參數(shù)列表的類型為指定的參數(shù)列表類型的方法 |
| @within() | 用于匹配持有指定注解的類的所有方法 |
| @target() | 用于匹配的持有指定注解目標對象的所有方法 |
| @args() | 用于匹配運行時 傳入的參數(shù)列表的類型持有 注解列表對應(yīng)的注解的方法 |
| @annotation() | 用于匹配持有指定注解的方法 |
| bean | bean(Bean的id或名字通配符)匹配特定名稱的Bean對象 |
三、類型匹配
1、說明
通常用在類型模式的和方法中
2、三種通配符
| 通配符 | 說明 |
|---|---|
| * | 匹配任何數(shù)量字符 |
| .. | 匹配任何數(shù)量字符的重復(fù),如在類型模式中匹配任何數(shù)量子包;而在方法參數(shù)模式中匹配任何數(shù)量參數(shù) |
| + | 匹配指定類型的子類型;僅能作為后綴放在類型模式后邊 |
四、操作運算符
1、說明
AspectJ使用 且(&&)、或(||)、非(?。﹣斫M合切入點表達式,由于在xml風格下,由于在XML中使用“&&”需要使用轉(zhuǎn)義字符“&&”來代替之,所以很不方便,因此Spring ASP 提供了and、or、not來代替&&、||、!
2、操作符
| 操作符 | 說明 | ||
|---|---|---|---|
&&或者 and
|
與操作符 | ||
| ` |
或者or` |
或操作符 | |
! 或者 not
|
非操作符 |
五、execution
1、說明
面粒度最小是達到方法級別,而execution表達式可以用于明確指定方法返回類型,類名,方法名和參數(shù)名等與方法相關(guān)的部件,并且在Spring中,大部分需要使用AOP的業(yè)務(wù)場景也只需要達到方法級別即可,因而execution表達式的使用是最為廣泛的
2、語法格式
execution([方法的可見性] 返回類型 [方法所在類的全路徑名] 方法名(參數(shù)類型列表) [方法拋出的異常類型])
3、栗子
- 切面類
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component @Aspect public class ExecutionAspect { @Pointcut("execution(public * com.wener.example.aop.execution.ExecutionService.test())") public void execuPoint() { } @Before("execution(public * com.wener.example.aop.execution.ExecutionService.add(..))") public void execuBefore() { System.out.println("核心方法之前!!!"); } @Before("execution(public * com.wener.example.aop.execution.ExecutionService.test(..))") public void execuAfter() { System.out.println("核心方法之后!!!"); } } - 目標類
import org.springframework.stereotype.Service; public interface ExecutionService { public void test(); public int add(String name); } @Service("service") public class ExecutionServiceImpl implements ExecutionService { @Override public void test() { System.out.println("測試方法核心代碼!!!"); } @Override public int add(String name) { System.out.println("添加的方法核心代碼!!!"); return 0; } } - 測試代碼
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-aspect.xml"); ExecutionService service = context.getBean("service", ExecutionService.class); service.add("1111"); service.test(); }
4、常見表達式
4.1、方法簽名定義切入點
- 匹配所有目標類的public方法,第一個為返回類型,第二個為方法名
execution(public * * (..))execution(* save* (..)) - 匹配所有目標類以xxx開頭的方法,第一個*代表返回任意類型
execution(* xxx* (..)) - 匹配目標類所有以xxx結(jié)尾的方法,并且其方法的參數(shù)表第一個參數(shù)可為任意類型,第二個參數(shù)必須為String
execution(**xxx(*,String))
4.2、類定義切入點
- 匹配Service接口及其實現(xiàn)子類中的所有方法
execution(* com.xxx.Service.*(..))
4.3、通過包定義切入點
- 匹配service包下的所有類的所有方法,但不包括子包
execution(* com.xxx.service.*(..)) - 匹配aop_part包下的所有類的所有方法,包括子包。
# 注意 (當".."出現(xiàn)再類名中時,后面必須跟" * ",表示包、子孫包下的所有類**) execution(* com.xxx.service..*(..)) - 匹配xxx包及其子包下的所有后綴名為service的類中,所有方法名必須以select為前綴的方法
execution(* com.xxx..*.*service.select*(..))
4.4、方法形參定義切入點
- 匹配所有方法名為add,且有兩個參數(shù),其中,第一個的類型為int 第二個參數(shù)是String
execution(* add(int, String)) - 匹配所有方法名為add,且至少含有一個參數(shù),并且第一個參數(shù)為int的方法
execution(* add(int, ..)) - 匹配所有方法名為add,匹配所有類型的參數(shù)
execution(* add(int, ..))