AOP切面讲解<二>切点(Pointcut)切入方式

504 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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() {
}
```