Springboot AOP 二:Pointcut表达式

表示式(expression)和签名(signature)

//Pointcut表示式
@Pointcut("execution(* com.savage.aop.MessageSender.*(..))")
//Point签名
private void log(){} 

表达式类型及结构

表达式类型包括:

  • execution:用于匹配方法执行的连接点;

  • within:用于匹配指定类型内的方法执行;

  • this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;

  • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

  • args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;

  • @within:用于匹配所以持有指定注解类型内的方法;

  • @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;

  • @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;

  • @annotation:用于匹配当前执行方法持有指定注解的方法;

表达式格式

表达式可以通过 &&、 ||、 !、 的方式进行组合。

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) 

其中后面跟着“?”的是可选项

括号中各个pattern分别表示:

  • 修饰符匹配(modifier-pattern?)
  • 返回值匹配(ret-type-pattern): 可以为*表示任何返回值, 全路径的类名等
  • 类路径匹配(declaring-type-pattern?)
  • 方法名匹配(name-pattern):可以指定方法名 或者 代表所有, set 代表以set开头的所有方法
  • 参数匹配((param-pattern)):可以指定具体的参数类型,
    多个参数间用“,”隔开
    各个参数也可以用"*" 来表示匹配任意类型的参数
    ".."表示零个或多个任意参数。
    如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型。
  • 异常类型匹配(throws-pattern?)

举例说明.

  • 任意公共方法的执行:
execution(public * *(..))
  • 任何一个以“set”开始的方法的执行:
execution(* set*(..))
  • AccountService 接口的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
  • 定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))
  • 定义在service包和所有子包里的任意类的任意方法的执行:
execution(* com.xyz.service..*.*(..))

第一个表示匹配任意的方法返回值, ..(两个点)表示零个或多个,第一个..表示service包及其子包,第二个表示所有类, 第三个*表示所有方法,第二个..表示方法的任意参数个数

  • 定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:
execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
  • pointcutexp包里的任意类:
within(com.test.spring.aop.pointcutexp.*)
  • pointcutexp包和所有子包里的任意类:
within(com.test.spring.aop.pointcutexp..*)
  • 实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:
this(com.test.spring.aop.pointcutexp.Intf)

当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型

  • 带有@Transactional标注的所有类的任意方法:
    @within(org.springframework.transaction.annotation.Transactional)
    @target(org.springframework.transaction.annotation.Transactional)
  • 带有@Transactional标注的任意方法:
@annotation(org.springframework.transaction.annotation.Transactional)

@within和@target针对类的注解,@annotation是针对方法的注解

  • 参数带有@Transactional标注的方法:
@args(org.springframework.transaction.annotation.Transactional)
  • 参数为String类型(运行是决定)的方法:
args(String)

织入

先来看一个列子

@AfterReturning(            
      pointcut="execution(* com.abc.service.*.access*(..)) && args(time, name)",            
      returning="returnValue")    
public void access(Date time, Object returnValue, String name) {      
    System.out.println("目标方法中的参数String = " + name);            
    System.out.println("目标方法中的参数Date = " + time);          
    System.out.println("目标方法的返回结果returnValue = " + returnValue);    
}

表达式中增加了args(time, name)部分,意味着可以在增强处理的签名方法(access方法)中定义"time"和"name"两个属性。

这两个形参的类型可以随意指定(access方法中指定),但一旦指定了这两个参数的类型,则这两个形参类型将用于限制该切入点只匹配第一个参数类型为Date, 第二个参数类型为String的方法(方法参数个数和类型若有不同均不匹配);

access方法只需要满足"time", "name"参数的顺序和pointcut中args(param1, param2)的顺序相同即可,"returnValue"位置顺序无所谓。

//将被access方法匹配
public String accessAdvice(Date d, String n) {    
    System.out.println("方法:accessAdvice");    
    return "aa";
}

你可能感兴趣的:(Springboot AOP 二:Pointcut表达式)