Spring AOP 中的切入点表达式

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?)
  1. modifiers-pattern - Method visibility (public, protected, private, *) ret-type-pattern - Return type of the method
  2. 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)
  3. name-pattern - method name (ex: set* - all setters)
  4. param-pattern - method parameters (.. - any number of parameters, java.lang.String - method taking String as parameter.
  5. throws-pattern - Method throwing this exception.

? – 表示可选指定,例如修饰符, throws_exception

* – 模式中的星号代表通配符

() – 对于 parameter_pattern 表示没有参数

(..) – 用于匹配具有零个或多个任意类型参数的 parameter_pattern

(*) – 模式匹配采用任何类型的一个参数的方法。

(*, String) - 匹配带有两个参数的方法,第一个是任意类型,第二个参数是字符串类型。

在下表中,我向您展示了一些最常用的示例,以便您更好地理解执行指示符。单词any代表下表中的所有。

ExplanationPattern
To match with the execution of any public methodexecution(public * *(..))
The match with any setterexecution(* set*(..))
Match with any method inside ActorRepository, defined inside a particular packageexecution(* 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 用于匹配目标对象的声明类具有给定注释的连接点(方法执行)。

ExplanationPattern
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 执行。

版权声明:著作权归作者所有。

相关推荐

Spring定时任务@Scheduled的cron表达式

基本语法cron表达式由6-7个时间域组成,每个时间域之间用空格隔开。格式:<秒> <分> <时> <日期> <月> <星期> <年份> 秒:取值范围0-59分:取值范围0-59时:取值范围0-23日期:每月的的几数,0-31月:取值范围1-12,或英文简

2018最新国内手机号码正则表达式

正则表达式^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$中国电信号段133、149、153、173、177、180、181、189、199中国联通号段130、131、132、145、155、156、166、175、176、185、186中国移动号段134(0-8)、135、136、137、138、139、147、150、151、152、157、

Python单个表达式合并字典的方法

有时需要把两个字典合并为一个新的字典。这里记录下以下三种使用单个表达式的来做合并的方式。方式一:自定义合并函数def merge_dictionaries(first_dict, second_dict): merged = first_dict.copy() merged.update(second_dict) return mergedd1 = { "A": "张三", "B":

Java 正则表达式不区分大小写

Java里使用正则表达式默认是区分大小写的,如果想要做不区分大小写匹配,有两种方式:表达式前加上前缀(?)在调用Pattern.compile()时,通过参数指定不区分大小写。表达式前加前缀(?)示例:Pattern pattern = Pattern.compile("(?)hello:\\s(.*)");调用Pattern.compile()时,通过参数指定不区分大小写示例:Pattern.c

Java14新特性:Switch表达式

Java 14正式发布switch表达式特性。在之前的两个 Java 版本Java12,Java13,switch特性只是预览版。新的switch表达式有助于避免一些bug,因为它的表达和组合方式更容易编写。switch新的表达式有两个特点:支持箭头表达式返回。支持yied和return返回值。Java 14之前switch语法:switch (day) { case MONDAY:

Python替代三元表达式

在Python里时没有三元表达式:条件表达式?表达式1:表达式2但有一些替代方案:true返回的值 if 条件表达式 else false返回的值value_when_true if condition else value_when_false示例:'Yes' if fruit == 'Apple' else 'No'通过赋值的方式:fruit = 'Apple'isApple = True i

Python swith表达式替代方案

Python里是没有像其他语言,如java里的switch...case这样的表达式。替代方案一:map下标def f(x): return { 'a': 1, 'b': 2, }[x]使用下标的方式,可以很简洁的获取想要的值。但这种方法有一个弊端,如果不存在时,不能返回一个默认的值。替代方案:使用if-elifif x == 'a': # 满足条件,

JavaScript正则表达式使用小手册

以下是JavaScript使用正则表达式的一个备忘录。测试正则表达式test()方法:用来测试字符串是否满足表达式。let testString = "My test string"; let testRegex = /string/; testRegex.test(testString);测试多个pattern可以使用或操作符(|)来连接多个表达式const regex = /yes|no|ma