Spring AOP 中的切入点表达式

简介
在本文中,您将了解用于将通知与目标连接点匹配的切入点表达式。 Spring AOP 使用 AspectJ 切入点表达式。您学习过切入点定义。 Spring AOP 仅支持方法执行连接点,因此您可以将切入点视为匹配 Spring bean 上方法的执行。
切入点:它是一个确定连接点的谓词表达式,因此允许我们控制通知的执行。
简单来说,切入点表达式就像一个正则表达式,它决定了将执行 Advice 的类和方法。
声明切入点
声明切入点很简单,您只需要使用@Pointcut(POINTCUT_EXPRESSION) 注释方法即可。
@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyTransfer() {} //pointcut signature
使用@Pointcut 是可选的,切入点表达式可以直接在通知注释中使用,如下所示。
- Before advice –
@Before
- Around advice –
@Around
- After returning –
@AfterReturning
- After throwing –
@AfterThrowing
- After (finally) advice –
@After
@Before("execution(* c.jbd.saop.gettingstarted.dao.*.add(..))")
public void allRepoAddMethods(JoinPoint joinPoint) {
//Aspect body
}
@Before 或 @Pointcut 注释中的术语执行称为切入点指示符。 Spring 提供了几个接下来要讨论的指示符。
支持的切入点指示符
Spring AOP 支持以下切入点指示符 (PCD)。
execution - 用于匹配方法执行连接点。这是使用最广泛的 PCD。
within - 用于匹配某些类型内的类的方法,例如包内的类。
@within - 用于匹配具有给定注释的类型(目标对象类)内的连接点。
this - 用于匹配连接点(方法的执行),其中 bean 引用(Spring AOP 代理)是给定类型的实例。
target - 用于匹配特定实例类型的目标对象。
@target – 用于匹配带有特定注释的目标对象。
args - 用于匹配其参数为特定类型的方法。
@args - 用于匹配使用特定注释注释其参数的方法。
@annotation - 用于匹配连接点的主题(方法)具有给定注释的连接点。
bean (idOrNameOfBean) – 此 PCD 允许您将连接点的匹配限制为特定命名的 Spring bean 或一组命名的 Spring bean(使用通配符时)。
AspectJ 提供了其他几个 Spring AOP 不支持的指示符,只支持上面提到的 PCD。
组合切入点表达式
您可以使用 AND – &&, OR – || 组合多个切入点表达式并不是 - !。您还可以按名称引用切入点表达式。以下示例显示相同:
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}
@Pointcut("within(com.jsbd.trading..*)")
private void inTrading() {}
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}
各种切入点指示符示例
execution
designator
这是大家需要知道的最广泛使用的指示符,用来匹配方法执行Joinpoint。 execution() 指示符的语法将在下面讨论。
execution(modifiers-pattern? return-type-pattern declaring-type-pattern? name-pattern( param-pattern)
throws-pattern?)
- modifiers-pattern - Method visibility (public, protected, private, *) ret-type-pattern - Return type of the method
- declaring-type-pattern - Package or class (ex: com.app.service.* - applies to all classes in this package, com.app.service.UserService - applies only to UserService class, * - all)
- name-pattern - method name (ex: set* - all setters)
- param-pattern - method parameters (.. - any number of parameters, java.lang.String - method taking String as parameter.
- throws-pattern - Method throwing this exception.
? – 表示可选指定,例如修饰符, throws_exception
* – 模式中的星号代表通配符
() – 对于 parameter_pattern 表示没有参数
(..) – 用于匹配具有零个或多个任意类型参数的 parameter_pattern
(*) – 模式匹配采用任何类型的一个参数的方法。
(*, String) - 匹配带有两个参数的方法,第一个是任意类型,第二个参数是字符串类型。
在下表中,我向您展示了一些最常用的示例,以便您更好地理解执行指示符。单词any代表下表中的所有。
Explanation | Pattern |
---|---|
To match with the execution of any public method | execution(public * *(..)) |
The match with any setter | execution(* set*(..)) |
Match with any method inside ActorRepository , defined inside a particular package | execution(* c.jbd.saop.gettingstarted.dao.ActorRepository.*(..) |
Match with any DAO delete() method with any type of arguments. | "execution(* c.jbd.app.dao.*.*(..))" |
Match any method inside any DAO with exactly one argument of any type. | "execution(* c.jbd.saop.gettingstarted.dao.*.*(*))" |
within
and @within
designators
within
用于匹配某些类型中的类的方法,例如包内的类。
类似地,@within 用于匹配目标对象的声明类具有给定注释的连接点(方法执行)。
Explanation | Pattern |
---|---|
Match with any joinpoint within business package. | "within(com.jbd.business.*)" |
Match with any joinpoint within business and its sub-packages | "within(com.jbd.business..*)" |
Match with any join point (method) execution where the declared type of the target object (the class) has an @Transactional annotation. | "@within( org.springframework.transaction.annotation.Transactional )" |
The this
designator
它将匹配限制为连接点(方法的执行),其中 bean 引用(Spring AOP 代理)是给定类型的实例。
例如,匹配代理实现 AccountService 接口的任何连接点(方法执行)。
"this(com.jbd.service.AccountService)"
The target
and @target
designators
目标指示符将匹配限制为目标对象(被代理的应用程序对象)是给定类型的实例的连接点(方法的执行)。例如当目标对象实现特定接口时。
例如,目标对象实现 AccountService 接口的任何连接点。
"target(com.jbd.service.AccountService)"
类似地,@target 用于将匹配限制为连接点(方法的执行),其中执行对象的类具有给定类型的注释。
例如,目标对象具有@Transactional 注释的任何连接点。
"@target(org.springframework.transaction.annotation.Transactional)"
The args
and @args
designators
args 将匹配限制为连接点(方法的执行),其中参数是给定类型的实例。
例如,任何采用单个参数并且在运行时传递的参数是可序列化的连接点(方法执行)。
同样,args 将匹配限制为连接点,其中传递的实际参数的运行时类型具有给定类型的注释。
例如,任何接受单个参数的连接点(方法执行),并且传递的参数的运行时类型具有 @Classified 注释:
"@args(com.jbd.security.Classified)"
The @annotation
designator
@annotation 指示符将匹配限制为连接点的主题(正在执行的方法)具有给定注释的连接点。
注意:@annotation 限制了方法具有给定注释的连接点的匹配,而 @within 匹配如果类具有注释。
例如,匹配执行方法具有@Transactional 注释的任何连接点(方法执行)。
"@annotation(org.springframework.transaction.annotation.Transactional)"
The bean
Pointcut designator
bean PCD 允许您将连接点的匹配限制为特定命名的 Spring bean 或一组命名的 Spring bean(使用通配符时)。
例如,Spring bean 上的任何连接点(方法执行),其名称与通配符表达式 *Manager 匹配。
"bean(*Manager)"
另一个示例,Spring bean 名称为 accountRepository 的任何连接点。
"bean(accountRepository)"
总结
从可读性的角度来看,我建议保持 Pointcut 表达式简单,同时确保编译器更容易缩小 Joinpoint 扫描的范围。例如。使用 with 或 @within 执行。