【Spring AOP】_切点类的切点表达式

目录

[1. 根据方法签名匹配编写切点表达式](#1. 根据方法签名匹配编写切点表达式)

[1.1 具体语法](#1.1 具体语法)

[1.2 通配符表达规范](#1.2 通配符表达规范)

[2. 根据注解匹配编写切点表达式](#2. 根据注解匹配编写切点表达式)

[2.1 实现步骤](#2.1 实现步骤)

[2.2 元注解及其常用取值含义](#2.2 元注解及其常用取值含义)

[2.3 使用自定义注解](#2.3 使用自定义注解)

[2.3.1 编写自定义注解@MyAspect](#2.3.1 编写自定义注解@MyAspect)

[2.3.2 编写切面类MyAspectDemo](#2.3.2 编写切面类MyAspectDemo)

[2.3.3 编写测试类及测试方法](#2.3.3 编写测试类及测试方法)


在前文使用注解编写AOP程序时,对于每一个切面,都是由切点和通知构成。

对于切点,有两种方式可以指明需要功能增强的类或类的方法:

(1)直接使用@Around、@Before、@After、@AfterReturning、@AfterThrowing等注解直接指明需要功能增强的类或方法,形如:

java 复制代码
@Around("execution(* com.example.bookmanagementsystem.controller.*.*(..))")

(2)通过@Pointcut注解指明公共切点,在其他通知前仍采取五个注解指明类或方法,但可通过@Pointcut标注的通知的方法名来简化编写,形如:

java 复制代码
 @Pointcut("execution(* com.zhouyou.demos.controller.*.*(..))")
    public void pc(){ }

    @Around("pc()")

但对于方式1的每一种切点声明方式和方式2的@Pointcut声明切点方式,都是采用方法的签名来匹配。

实际上切点表达式有两种编写方式,可根据方法的签名匹配,也可根据注解匹配。

1. 根据方法签名匹配编写切点表达式

1.1 具体语法

1.2 通配符表达规范

1、*匹配诶任意字符,值匹配一个元素,包名使用*表示任意包,类名使用*表示任意类,返回值使用*表示任意返回值,方法名使用*表示任意方法,参数使用*表示一个任意类型的参数;

2、..匹配多个连续的任意符号。..配置包名表示此包及其所有子包,..配置参数表示任意个任意类型的参数;

如:

java 复制代码
execution(* com.zhouyou.demos.controller.*.*(..)

表示controller包下所有的类的所有方法;

2. 根据注解匹配编写切点表达式

除以上采用方法签名的方式外,还可以使用@annotation注解的方式编写切点表达式,这种方式通常应用在某个切面类需要匹配多个controller类中的部分方法的情况;

2.1 实现步骤

1、编写自定义注解;

2、使用@annotation表达式来描述切点;

3、在连接点的方法上添加自定义注解;

2.2 元注解及其常用取值含义

  1. @Target:表示注解所修饰的对象范围:

2、@Retention:表示注解的生命周期:

2.3 使用自定义注解

2.3.1 编写自定义注解@MyAspect

在aspect包下创建MyAspect注解类:

在MyAspect类中使用元注解指明其修饰对象范围和生命周期:

java 复制代码
package com.zhouyou.demos.aspect;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 表示该注解用于标注方法
@Target(ElementType.METHOD)
// 表示该注解声明周期在程序执行时有效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {
}

2.3.2 编写切面类MyAspectDemo

java 复制代码
package com.zhouyou.demos.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class MyAspectDemo {
    @Before("@annotation(com.zhouyou.demos.aspect.MyAspect)")
    public void doBefore(){
        log.info("MyAspectDemo doBefore");
    }
    @After("@annotation(com.zhouyou.demos.aspect.MyAspect)")
    public void doAfter(){
        log.info("MyAspectDemo doAfter");
    }
}

2.3.3 编写测试类及测试方法

在controller包下创建TestCotroller1和TestController2两个测试类,分别设置3个和2个不同返回值的测试方法,并在TestController1的test12方法和TestController2的test22方法前增加自定义的@MyAspect注解。

  1. TestController1:
java 复制代码
package com.zhouyou.demos.controller;

import com.zhouyou.demos.aspect.MyAspect;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test1")
public class TestController1 {
    @RequestMapping("/test11")
    public String test11(){
        return "aop";
    }
    @MyAspect
    @RequestMapping("/test12")
    public Integer test12(){
        return 12;
    }
    @RequestMapping("/test13")
    public boolean test13(){
        return true;
    }
}
  1. TestController2:
java 复制代码
package com.zhouyou.demos.controller;

import com.zhouyou.demos.aspect.MyAspect;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test2")
public class TestController2 {
    @RequestMapping("/test21")
    public String test21(){
        return "hello";
    }
    @MyAspect
    @RequestMapping("/test22")
    public Integer test22(){
        return 22;
    }
}

启动项目,依次按顺序访问test1/test11至test1/test13,和test2/test21、test2/test22,控制台日志如下:

只有添加了自定义注解@MyAspect修饰的TestController1的test12方法和TestController2的test22方法执行时,切面通知doBefore和doAfter执行,访问其余方法时,切面通知均未执行。

相关推荐
神奇小汤圆4 分钟前
金三银四Java面试题及答案汇总(2026持续更新)
后端
Ray Liang11 分钟前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
颜酱13 分钟前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
神奇小汤圆17 分钟前
加了 limit 1,查询竟然变慢了?
后端
Java水解23 分钟前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
Java水解26 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
千寻girling29 分钟前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
南风99930 分钟前
Claude code安装使用保姆级教程
后端
爱泡脚的鸡腿31 分钟前
Node.js 拓展
前端·后端
蚂蚁背大象2 小时前
Rust 所有权系统是为了解决什么问题
后端·rust