AOP表达式中常用的指示符,如图(摘自慕课网):
包、类型
- within()
表示匹配该包以及子包下面所有类的方法
/**
* within(com.xanthuim.springaop.service..*)
*/
@Pointcut("within(com.xanthuim.springaop.service.impl.*)")
public void pointcut() {
}
类(对象)
- this()
匹配类、接口实现类中所有方法,包括未在接口中声明的方法 - target()
匹配类、接口实现类中所有方法,包括未在接口中声明的方法。在一般情况下与this()一致,二者的区别体现在通过引介切面产生代理对象时的具体表现。具体参考:https://blog.csdn.net/yangshangwei/article/details/77861658 - bean()
拦截Spring环境中Bean类的方法,也可以使用匹配符
@Pointcut("bean(orderServiceImpl)")
public void pointcut() {
}
方法
- execution()
完整的表达式:execution(修饰符通配符 返回值通配符 包名通配符 方法名通配符(参数通配符) 异常通配符)
以public String com.youngledo.service.impl.CustomerServiceImpl.getName()
为例说明匹配符的写法。
- 修饰符可以省略不写:
String com.youngledo.service.impl.CustomerServiceImpl.getName()
- 返回值可以使用通配符
*
,表示任意返回值,如需完全匹配写具体返回类型即可。
* com.youngledo.service.impl.CustomerServiceImpl.getName()
- 包名可以使用通配符
*
,但有几层包就得写几个*
,如com.youngledo.service.impl
写成这样*.*.*.*
:
* *.*.*.*.CustomerServiceImpl.getName()
- 包名也可以使用
..
代表当前包及其子包
* com..CustomerServiceImpl.getName()
- 类名和方法名可以使用通配符
*
* com..*.*()
- 当然类名和方法名也可以部分匹配:
* com..Customer*.getName()
- 参数列表可以使用具体类型来表示。基本数据类型(如int、char、short这种关键字)直接写就可,而引用类型必须是
包名.类名
,如java.lang.Integer:
* com..*.*(java.lang.Integer)
- 参数列表也可以使用通配符
*
,表示任意类型,但无参的方法不会匹配到:
* com..*.*(*)
- 参数列表也可以
..
表示任意类型,有参无参都可以:
* com..*.*(..)
- 全匹配:
* *..*.*(..)
一般来说只对业务层的方法进行增强,即:
* com.youngledo.service.impl.*.*(..)
// 匹配任何以find开头、任何参数的方法
@Pointcut("execution(* *..find*(..))")
public void pointcut() {
}
参数
- args()
// 匹配第一个参数为Long类型,并且必须是com.xanthuim.springaop.service包下的任意类的方法
@Pointcut("args(Long, ..) && within(com.xanthuim.springaop.service.*)")
public void pointcut() {
}
注解(注意注解有继承也会受影响)
- @annotation()
// 匹配方法上标注有@DataSource注解的方法
@Pointcut("@annotation(com.xanthuim.springaop.annotation.DataSource)")
public void pointcut() {
}
- @within()
// 匹配类上标注有@DataSource注解的方法,并且在该类的子类中,那些没有重写的父类方法也会被匹配到,同时要求注解的RetentionPolicy级别为CLASS
@Pointcut("@within(com.xanthuim.springaop.annotation.DataSource)")
public void pointcut() {
}
- @target()
// 直接匹配目标对象类上标注有@DataSource注解的方法,并且要求注解的RetentionPolicy级别为RUNTIME
@Pointcut("@target(com.xanthuim.springaop.annotation.DataSource)")
public void pointcut() {
}
- @args()
// 匹配参数上标注有@DataSource的方法。比如login(User user)方法中的User类被@DataSource标注了,那么这个方法就可以被拦截。
@Pointcut("@args(com.xanthuim.springaop.annotation.DataSource)")
public void pointcut() {
}