AOP-切入点表达式-execution
springboot使用aop时常用的两种切入点表达式:
1.execution(…): 根据方法的签名来匹配
2.@annotation(…): 根据注解匹配
execution 主要根据方法的返回值,包名,类名,方法名,方法参数等信息来匹配,语法为:
execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
其中带?的表示可以省略的部分:
- 访问修饰符: 可省略 (比如: public, protected)
- 包名.类名: 可省略(不建议省略)
- throws 异常: 可省略 (注意是方法上声明抛出的异常, 不是实际抛出的异常)
使用样例:
@Pointcut("execution(* com.qy.service.impl.DeptService.*(..))")
public void pt(){}
@Around("execution(* com.qy.service.impl.DeptService.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("around before...");
//调用目标方法的原始方法执行
Object result = joinPoint.proceed();
log.info("around after...");
return result;
}
其中:
- 第一个*: 表示返回值是任意类型(Object),可以改成具体的返回值
- 第二个*: 表示是DeptService下的所有方法,可以改成具体的方法名
- (…): 方法参数是任意,可以改成具体的参数类型,如(java.lang.Integer)
- 此处访问修饰符和throws 异常都以省略
通配符:
-
*: 单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数
也可以通配包、类、方法名的一部分//返回值是任意类型(Object) com.任意一级包.servic.所有类.update开头的所有方法(任意类型的一个参数) execution(* com.*.service.*.update*(*))
-
… : 多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
//返回值是任意类型(Object) com.qy.任意层级的包.DeptService.所有方法(任意类型的任意个参数) execution(* com.qy..DeptService.*(..))
通配所有方法:
execution(* *(..)) // 慎用
多个方法匹配:
-
根据业务需要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式。
@Pointcut("execution(* com.qy.service.impl.DeptService.list()) ||" + "execution(* com.qy.service.impl.DeptService.delete(java.lang.Integer))")
书写建议:
- 所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是find开头,更新类方法都是update开头。
- 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。
- 在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用…,使用*匹配单个包。