持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
我们在上一节学习了AOP切面讲解Pointcut的切入方式主要分为四类:方法切点、目标类切点、方法入参切点、代理类切点。
一、作用方式
方法切点的使用方式:
- execution,作用方法,最常用。指定方法返回类型,类名,方法名,参数名等与方法相关的部件。
- @annotation,作用方法。方法注解类名;当执行的方法上拥有指定的注解时生效。
目标类切点的使用方式:
- within,作用目标类。指定全路径类名;指定某些类型的全部方法执行,也可用来指定一个包。
- target,作用目标类。指定类名;当被代理的对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
- @within,作用目标类。类型注解类名。与@target类似,只要目标类或父类上有指定的注解即可。
- @target,作用目标类。类型注解类名;当代理的目标对象上拥有指定的注解时生效。
方法入参切点的使用方式:
- args,作用参数。指定全路径的类名;当执行的方法的参数是指定类型时生效。
- @args,作用参数。类型注解类名;当执行的方法参数类型上拥有指定的注解时生效。
代理类切点的使用方式:
-
this:Spring Aop是基于动态代理的,生成的bean也是一个代理对象,this就是这个代理对象,当这个对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
-
bean:当调用的方法是指定的bean的方法时生效。(Spring AOP自己扩展支持的),这是Spring增加的一种方法,spring独有;bean用于匹配当调用的是指定的Spring的某个bean的方法时。
bean(abc)匹配Spring Bean容器中id或name为abc的bean的方法调用。
bean(user*)匹配所有id或name为以user开头的bean的方法调用。
- reference pointcut:(经常使用)表示引用其他命名切入点,只有@ApectJ风格支持
二、符号逻辑运算
1、Pointcut定义时,还可以使用&&、||、! 这三个运算。进行逻辑运算。可以把各种条件组合起来使用。
// 签名:消息发送切面
@Pointcut("execution(* com.fsx.run.MessageSender.*(..))")
private void logSender(){}
// 签名:消息接收切面
@Pointcut("execution(* com.fsx.run.MessageReceiver.*(..))")
private void logReceiver(){}
// 只有满足发送 或者 接收 这个切面都会切进去
@Pointcut("logSender() || logReceiver()")
private void logMessage(){}
此场景中logMessage()将匹配任何MessageSender和MessageReceiver中的任何方法。
2、bean(userService) && args()匹配id或name为userService的bean的所有无参方法。
2、bean(userService) || @annotation(MyAnnotation)匹配id或name为userService的bean的方法调用,或者是方法上使用了MyAnnotation注解的方法调用。
3、bean(userService) && !args()匹配id或name为userService的bean的所有有参方法调用。
三、使用示例
1、execution作用方法
execution(* (..)) execution表示匹配方法
execution(public * com.fsx.run.UserService.(..)) 匹配com.fsx.run.UserService中所有的公有方法
execution(* com.fsx.run...(..))匹配com.fsx.run包及其子包下的所有方法
2、within是用来指定类型的,指定类型(实现类)中的所有方法将被拦截。
@Pointcut("within(com.fsx.run.service.impl.AServiceImpl)")
public void pointCut() {
}
3、this
可以拦截到AService所有的子类的所有外部调用方法
@Pointcut("this(com.fsx.run.service.AService*)")
public void pointCut() {
}
4、target
@Pointcut("target(com.fsx.run.service.impl.AServiceImpl)")
public void pointCut() {
}
5、args:
args用来匹配方法参数的。
- 1、“args()”匹配任何不带参数的方法。
- 2、“args(java.lang.String)”匹配任何只带一个参数,而且这个参数的类型是String的方法。
- 3、“args(…)”带任意参数的方法。
- 4、“args(java.lang.String,…)”匹配带任意个参数,但是第一个参数的类型是String的方法。
- 5、“args(…,java.lang.String)”匹配带任意个参数,但是最后一个参数的类型是String的方法。
6、 @annotation:使用得也比较多
@annotation用于匹配方法上拥有指定注解的情况。
// 可以匹配所有方法上标有此注解的方法
@Pointcut("@annotation(com.fsx.run.anno.MyAnno)")
public void pointCut() {
}
还可以这么写,非常方便的获取到方法上面的注解
@Before("@annotation(myAnno)")
public void doBefore(JoinPoint joinPoint, MyAnno myAnno) {
System.out.println(myAnno); //@com.fsx.run.anno.MyAnno()
System.out.println("AOP Before Advice...");
}
7、bean(AServiceImpl) && !args()匹配userService所有有参方法
```
@Pointcut("bean(AServiceImpl) && !args()")
public void pointCut() {
}
```