Pointcut 表达式

简介: 1. AOP 概念篇今天介绍 Pointcut 的表达式

网络异常,图片无法展示
|

  1. AOP 概念篇

今天介绍 Pointcut 的表达式


通配符


常见的通配符如下


..

含义一:方法表达式中、代表任意数量的参数

@Service
public class HelloService {
    public void sayHi(String name) {
        System.out.println("hi," + name);
    }
    public void sayHi(String firstName, String lastName) {
        System.out.println("hi," + firstName + lastName);
    }
}
@Pointcut("execution(public void com.example.junitspringboot.service.HelloService.sayHi(..))")
 public void pointcut(){}
复制代码


那么上面的 Pointcut 表达式就能将 HelloService 中的两个连接点都包括进去。

  • 连接点:程序执行的某个特定位置,比如某个方法调用前、调用后,方法抛出异常后,对类成员的访问以及异常处理程序块的执行等。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。它自身还可以嵌套其他的 Joinpoint。AOP 中的 Joinpoint 可以有多种类型:构造方法调用,字段的设置和获取,方法的调用,方法的执行,异常的处理执行,类的初始化。Spring 仅支持方法执行类型的 Joinpoint。


含义二:类定义表达式中、代表任意子包

@Component
@Aspect
public class ServiceAop {
    @Pointcut("execution(public void com.example.junitspringboot..HelloService.sayHi(..))")
    public void pointcut(){}
    @Around("pointcut()")
    public Object before(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("before");
        return proceedingJoinPoint.proceed();
    }
}
// 注意包名
package com.example.junitspringboot.service.inner;
import org.springframework.stereotype.Service;
@Service("innerHelloService")
public class HelloService {
    public void sayHi(String firstName, String lastName) {
        System.out.println("hi," + firstName + lastName);
    }
}
// 注意包名
package com.example.junitspringboot.service;
public class HelloService {
    public void sayHi(String name) {
        System.out.println("hi," + name);
    }
}
复制代码


+

匹配给定类及其子类

public interface Person {
    void say();
}
@Service
public class Man implements Person{
    @Override
    public void say() {
        System.out.println("man");
    }
}
@Service
public class Woman implements Person {
    @Override
    public void say() {
        System.out.println("woman");
    }
}
@Pointcut("within(com.example.junitspringboot.service.Person+)")
public void pointcut(){}
复制代码

那么接口 Person 的子类所有实现的方法都会被增强。


*

匹配任意数量的字符

// com.example.junitspringboot.service 包所有的类的所有方法
@Pointcut("within(com.example.junitspringboot.service.*)")
public void pointcut1(){}
// 所有以 say 开头的方法
@Pointcut("execution(* say*(..))")
public void pointcut2(){}
复制代码


execution


使用得最多的表达式、用于指定方法的执行。? 表示非必填

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? 
  name-pattern(param-pattern) throws-pattern?)
复制代码
  • modifiers-pattern?  表示修饰符、如 public、protected
  • ret-type-pattern 返回类型、必填。 如果使用通配符 * 代表任意的返回类型
  • declaring-type-pattern? 表示声明方法的类。
  • name-pattern 表示方法名。
  • param-pattern 表示方法参数、如果使用通配符 .. 则代表任意参数
  • throws-pattern? 表示方法抛出的异常


例子

execution(public * com.example..say*(..))  
复制代码
  • 修饰符为 public
  • 任意返回类型
  • 在 com.example 包或者其子包下
  • 方法名称以 say 开头
  • 任意参数
@Pointcut("execution( * say*(..))")
复制代码
  • 任意返回类型
  • 方法名称以 say 开头
  • 任意参数
@Pointcut("execution(* *(..) throws Exception)")
复制代码
  • 方法声明抛出 Exception 的任意方法


within

指定特定类型、类型中所有的方法都被拦截。

@Pointcut("within(com.example.junitspringboot.service.Person)")
复制代码
  • Person 类所有外部的方法调用都被拦截
@Pointcut("within(com.example.junitspringboot.service.Person+)")
复制代码
  • Person 类及其子类所有外部的方法调用都被拦截
@Pointcut("within(com.example.junitspringboot.service..*)"
复制代码
  • 所有在 com.example.junitspringboot.service 包以及子包下的所有类的所有外部调用方法


this

this通过判断代理类是否按类型匹配指定类来决定是否和切点匹配。 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配。 this中使用的表达式必须是类型全限定名,不支持通配符。

public class ServiceAop implements Ordered {
    @Pointcut("this(com.example.junitspringboot.service.ISwimming)")
    public void thisPointcut(){}
    @Before("thisPointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("before");
    }
    @Override
    public int getOrder() {
        return 1;
    }
}
// 使用引介使 Man 也实现 ISwimming 接口
@Component
@Aspect
public class IntroductionAop implements Ordered {
    @DeclareParents(value = "com.example.junitspringboot.service.Man", defaultImpl = Swimming.class)
    public ISwimming swimming;
    @Override
    public int getOrder() {
        return 0;
    }
}
// 微信公众号:CoderLi
public interface ISwimming {
    void swim();
}
// 微信公众号:CoderLi
@Service
public class Man implements Person{
    @Override
    public void say() {
        System.out.println("man");
    }
}
 ConfigurableApplicationContext context = SpringApplication.run(JunitSpringBootApplication.class, args);
 context.getBean(Man.class).say();
 ((ISwimming) context.getBean(Man.class)).swim();
复制代码

当我们调用 swim 方法的时候、会被拦截增强。当我们调用 say 方法的时候、同样也会被拦截增强,这个就是 this 会将代理类实现的其他接口的方法也会被拦截增强


target

target 通过判断目标类是否按类型匹配指定类来决定连接点是否匹配. 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

@Pointcut("target(com.example.junitspringboot.service.ISwimming)")
复制代码

同样也是上面的例子。修改切点表达式为 target 、say 方法不再被拦截增强。


args

用来匹配参数

@Pointcut("args(..)")
复制代码
  • 匹配任意参数的方法
@Pointcut("args()")
复制代码
  • 匹配任何不带参数的方法


@target

匹配当被代理的目标对象对应的类型及其父类型上拥有指定的注解时

@Pointcut("@target(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")
复制代码
  • 匹配在包 com.example.junitspringboot..* 下所有被 AopFlag 修饰的类的所有方法


@args

@args匹配被调用的方法上含有参数,且对应的参数类型上拥有指定的注解的情况。

@Pointcut("@args(com.example.junitspringboot.anno.AopFlag)")
// 微信公众号:CoderLi
@AopFlag
public class Data {
}
public interface Person {
    void say(Data data);
}
复制代码


@within

@within用于匹配被代理的目标对象对应的类型或其父类型拥有指定的注解的情况,但只有在调用拥有指定注解的类上的方法时才匹配。

@Pointcut("@within(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")
复制代码

这个功能上貌似跟 @target 有点像了


@annotation

也是比较常用的一个注解、用于匹配方法上拥有指定注解的情况。

@Pointcut("@annotation(com.example.junitspringboot.anno.AopFlag) && within(com.example.junitspringboot..*)")
复制代码


bean

Spring 特有的一个表达式。

@Pointcut("bean(man)")
复制代码

拦截该 bean 的所有方法

10 种切点的表达式介绍完毕



目录
相关文章
|
6月前
|
Java Spring
Spel 表达式
在开发中,模板占位和参数动态替换常使用Spring的SpEL表达式。SpEl能从注解获取方法参数
41 0
|
6月前
|
编译器 C++
C++系列七:表达式
C++系列七:表达式
|
Java Spring
Spring AOP切点表达式(Pointcut)详解
Spring 的 AOP 中的一个核心概念是切点(Pointcut),切点表达式定义通知(Advice)执行的范围。
4097 0
|
6月前
Q表达式
Q表达式。
48 5
|
6月前
|
SQL 数据库 Python
F表达式
F表达式。
39 4
|
6月前
|
Java 开发者 Spring
什么是切点表达式语言?
【4月更文挑战第30天】什么是切点表达式语言?
38 0
|
6月前
@Pointcut 使用
@Pointcut 使用
73 1
|
6月前
|
安全 C++ 开发者
c++表达式详细介绍
前言 表达式是 C++ 语言的基石之一,它们在程序中执行计算、赋值、逻辑判断和更多操作。本文旨在提供对 C++ 表达式各个方面的全面了解,包括基础概念、类型、求值规则以及高级主题。
134 0
|
12月前
|
Java Spring
SpringAOP中Aspect优先级与切面表达式详解
SpringAOP中Aspect优先级与切面表达式详解
196 0
|
XML Java 数据格式
AOP:组合使用多个切入点表达式(Combining pointcut expressions)
AOP:组合使用多个切入点表达式(Combining pointcut expressions)
1239 0