Lecture15-切面-[实验04]切入点表达式语法

文章目录

    [toc]

    单词词性音标含义
    executionn./ˌeksɪˈkjuːʃn/执行(AOP切点表达式关键字,用于匹配方法执行连接点,可指定方法返回值、类名、方法名及参数)
    withinprep./wɪˈðɪn/在……之内(AOP切点表达式关键字,用于匹配指定类或包中的所有方法执行连接点)
    argsn. (复数)/ɑːɡz/参数(AOP切点表达式关键字,用于匹配参数类型符合指定条件的方法执行连接点)
    annotationn./ˌænəˈteɪʃn/注解(AOP切点表达式关键字,用于匹配被指定注解标注的方法或类的连接点)

    Lecture15-切面-[实验04]切入点表达式语法

    1、切入点表达式的作用

    images


    2、表达式总体结构

    • 如果只有一个核心表达式,那就无需使用逻辑运算符
    • 如果核心表达式有多个,那就需要使用逻辑运算符连起来,以便计算出一个最终结果
    • 组合表达式中,&& 优先级高于 ||,建议使用括号明确优先级

    image-20250525171216353


    3、核心表达式

    ①总体介绍

    类型匹配维度示例Spring 版本要求
    execution方法执行execution(public * *(..))所有版本(从 Spring 1.0 起)
    within类范围within(com.example.service.*)所有版本
    args参数类型args(String, int)所有版本
    @annotation方法注解@annotation(Transactional)Spring 2.0+
    @within类注解@within(MyService)Spring 2.0+
    @target目标对象类注解@target(MyService)Spring 2.0+
    @args参数类型注解@args(Validated)Spring 2.0+
    this代理对象接口this(MyInterface)所有版本
    target目标对象接口target(MyInterface)所有版本

    ② execution

    [1]总述

    • 作用:匹配方法执行连接点,是最常用的切入点类型。

    • 语法:

      execution(权限修饰符? 返回类型 类路径?方法名(参数) throws 异常?)
      
    • 示例:

      execution(public * com.example.service.*.*(..))  // 匹配Service包下所有public方法
      

    [2]细节:权限修饰符部分

    image-20250525193742056

    • 权限修饰符可以省略,省略表示所有范围的权限修饰符都可以匹配

      • public:当前整个工程都可以访问
      • protected:本类、本包和子类
      • default:本类和本包
      • private:本类(所以切入点表达式省略权限修饰符,有可能锁定私有方法,需要注意)
    • 权限修饰符这里要么省略,要么明确指定,不能使用星号!

    // 正确写法
    // 例1:省略了权限修饰符的部分
    execution(int com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 例2:这里的星号是针对方法返回值类型使用通配符,而权限修饰符部分是被省略的
    execution(* com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 例3:权限修饰符和方法返回值类型都明确指定
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 错误写法
    execution(* int com.atguigu.spring.api.Calculator.mul(int, int))
    

    [3]细节:返回类型部分

    • 明确指定返回类型
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
    
    • 用星号表示任何返回类型都可以
    execution(public * com.atguigu.spring.api.Calculator.mul(int, int))
    

    [4]细节:全类名部分

    • 可以省略
    @Pointcut("execution(public int mul(int, int))")
    
    • 可以明确指定
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
    
    • 可以使用星号代替整个全类名
    execution(public int *.mul(int, int))
    
    • 对于全类名中的包名部分:
    // 单独的一个星号,表示这个层级的包名不限
    execution(public int *.atguigu.spring.api.Calculator.mul(int, int))
    
    // 星号后面跟两个点,表示包名不限、层次深度不限
    execution(public int *..Calculator.mul(int, int))
    
    • 对于全类名中的类名部分:
    // 类名完整指定
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 整个类名使用星号
    execution(public int com.atguigu.spring.api.*.mul(int, int))
        
    // 类名仅部分指定
    // 例如下面表达式表示匹配以Calculator开头的类名
    execution(public int com.atguigu.spring.api.Calculator*.mul(int, int))
    

    [5]细节:方法名部分

    // 方法名完整指定
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 方法名整个使用星号
    execution(public int com.atguigu.spring.api.Calculator.*(int, int))
        
    // 方法名仅部分指定
    // 例如下面表达式表示匹配以mul开头的方法名
    execution(public int com.atguigu.spring.api.Calculator.mul*(int, int))
    

    [6]细节:参数列表部分

    // 完整明确指定参数列表
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int))
        
    // 仅部分指定
    execution(public int com.atguigu.spring.api.Calculator.mul(int, int, ..))
    execution(public int com.atguigu.spring.api.Calculator.mul(int, .., int))
    
    // 参数列表任意
    execution(public int com.atguigu.spring.api.Calculator.mul(..))
    

    [7]典型用法举例

    execution(* *..*Service.*(..))
    

    ③within

    • 作用:匹配指定类型内的方法执行。
    • 语法:
      within(类路径表达式)
      
    • 示例:
      within(com.example.service.*)  // 匹配Service包下所有类的方法
      within(com.example.service.UserService+)  // 匹配UserService及其子类的方法
      

    ④ args

    • 作用:匹配参数类型符合指定条件的方法。
    • 语法:
      args(参数类型列表)
      
    • 示例:
      args(java.lang.String, int)  // 匹配第一个参数为String,第二个为int的方法
      

    ⑤@annotation

    [1]总述

    • 作用:匹配带有指定注解的方法。

    • 语法:

      @annotation(注解全限定名)
      

      全限定名就是全类名

    • 示例:

      @annotation(org.springframework.transaction.annotation.Transactional)  // 匹配带@Transactional的方法
      

    [2]测试:自定义注解

    image-20250526084211254

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AtguiguDoSth {
    
        // 声明这个属性是为了将来注解标记在不同方法上,可以设置不同的值
        String info() default "happy";
    
    }
    

    [3]测试:把注解标记于目标方法

    image-20250526084309485

    @Override
    @AtguiguDoSth(info = "timi")
    public int sub(int i, int j) {
    
        int result = i - j;
    
        System.out.println("方法内部 result = " + result);
    
        return result;
    }
    

    [4]测试:切入点表达式

    image-20250526084402322

    @Component
    public class MyPointCut {
    
        @Pointcut("@annotation(com.atguigu.spring.annotation.AtguiguDoSth)")
        public void fixPointCut(){}
    
    }
    

    [5]测试:在通知方法读取注解

    image-20250526084525786

    // 1、获取 MethodSignature 对象
    MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
    
    // 2、获取我们标记在目标方法上的注解
    AtguiguDoSth annotation = methodSignature.getMethod().getAnnotation(AtguiguDoSth.class);
    
    // 3、读取注解中设置的属性
    String info = annotation.info();
    

    ⑥@within

    • 作用:匹配类上带有指定注解的所有方法。
    • 语法:
      @within(注解全限定名)
      
    • 示例:
      @within(com.example.annotation.MyService)  // 匹配类上有@MyService注解的所有方法
      

    ⑦ @target

    • 作用:匹配目标对象类上带有指定注解的方法。
    • 语法:
      @target(注解全限定名)
      
    • 示例:
      @target(com.example.annotation.MyService)  // 匹配目标对象类有@MyService注解的方法
      

    ⑧@args

    • 作用:匹配参数类型上带有指定注解的方法。
    • 语法:
      @args(注解全限定名)
      
    • 示例:
      @args(com.example.annotation.Validated)  // 匹配参数类型带有@Validated注解的方法
      

    ⑨this

    • 作用:匹配代理对象实现了指定接口的方法。
    • 语法:
      this(接口类型)
      
    • 示例:
      this(com.example.service.MyService)  // 匹配代理对象实现了MyService接口的方法
      

    ⑩target

    • 作用:匹配目标对象实现了指定接口的方法。
    • 语法:
      target(接口类型)
      
    • 示例:
      target(com.example.service.MyService)  // 匹配目标对象实现了MyService接口的方法
      

    ⑪ 组合表达式

    • 作用:使用逻辑运算符组合多个切入点表达式。
    • 运算符:
      • &&(与)、||(或)、!(非)
    • 示例:
      execution(* com.example.service.*.*(..)) && !within(com.example.service.impl.*)  // 匹配Service包但排除impl子包
      

    end