表示式(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";
}
网友评论