AOP - 切点表达式

execution 表达式

// 语法格式
execution(方法访问修饰符? 方法返回类型 方法所在包路径?.方法名(方法参数类型) 方法抛出的异常?)
  1. 访问修饰符:public、protected、private 等,可省略,省略表示任意修饰符

    // com.example.service.UserService 类中的所有 public 方法
    execution(public * com.example.service.UserService.*(..))
    
  2. 返回类型:指方法返回类型,可以是具体的类名,比如 String、void、com.example.User 等,* 表示任何类型

  3. 包路径:可选部分,指定方法所在的类或接口的模式。可以是具体的类名、接口名或 * 表示任意包, .. 表示子包

    // 指定类下所有方法作为切点(UserService 类中的所有方法)
    execution(* com.example.service.UserService.*(..))
    
    // 指定接口所有实现类的方法作为切点(UserServiceInterface 接口的所有类中的方法)
    execution(* com.example.service.UserServiceInterface.*(..))
    
    // 指定子类所有方法作为切点(+表示 BaseService 类及其所有子类的方法)
    execution(* com.example.service.BaseService+.*(..))
    
    // 指定 com.example.service 包及其子包下所有类的方法作为切点(com.example.service 包及其子包中的所有方法)
    execution(* com.example.service..*.*(..))
    
  4. 方法名:方法名称,* 表示任何方法

  5. 方法参数:指方法参数类型,.. 表示任意数量的参数,* 表示任意类型

    // com.example.service.UserService 类中的 addUser 方法(第一个参数为 String 类型,其余参数可以是任意类型)
    execution(* com.example.service.UserService.addUser(String, ..))
    
    // 第一个参数为 String 类型,第二个参数为 Integer 类型,其余参数可以是任意类型
    execution(* com.example.service.UserService.addUser(String, Integer ..))
    
  6. 异常:方法抛出的异常,可选项

    // com.example.service.UserService 类下抛出 Exception 的所有方法
    execution(* com.example.service.UserService.*(..) throws Exception)
    

within 表达式

execution 完全可以代替 within 的功能

*表示任意类,.. 表示子包和的所有类(..* 和 .. 是相同功能只是语义上有些许着重的意思 )

// 语法格式(指定类或包,不能具体到方法级别)
within(范围)
  1. 匹配特定的类

    // 匹配 UserService 类中的所有方法
    within(com.example.service.UserService)
    
  2. 匹配特定的包

    // com.example.service 这个包及其子包下的所有类
    within(com.example.service..*)
    // 选择的切点是一样的
    within(com.example.service..)
    

@annotation 表达式

这也是比较常用的表达式,语法也比较简单

// 标注了 @GetMapping 的方法将作为切点
@annotation(org.springframework.web.bind.annotation.GetMapping)

其他表达式

除了 execution、within、@annotation 表达式之外还有 this、target、args 表达式,不过这三种不常用

组合表达式

// AND
@Pointcut("execution(* com.example.service.*(..)) && within(com.example.service.UserService)")

// OR
@Pointcut("execution(* com.example.service.*(..)) || execution(* com.example.repository.*(..))")

// NOT
@Pointcut("execution(* com.example.service.*(..)) && !execution(* com.example.service.UserService.*(..))")

表达式示例

  • 某个特殊的方法:com.example.service.UserService 类中所有以 find 开头的公共方法

    execution(public * com.example.service.UserService.find*(..))

  • 类中的所有方法:com.example.service 包下所有类的所有方法

    execution(* com.example.service.*.*(..))

  • 特定参数类型的方法:com.example.service.UserService 类中接受一个 User 对象作为参数的方法

    execution(String com.example.service.UserService.getName(..))

  • com.example.service 包及其子包下的所有类中的所有方法

    execution(* com.example.service..*.*(..))

  • com.example.service 包及其子包下的所有类中的所有方法

    within 不能指定某个方法,本身是类级别的;execution 可以指定某个方法

    如果exection 切某个包及其子包下所有方法就和 within 功能一样了

    within(com.example.service..*)

  • 带有特定注解的方法:被 @Loggable 注解标记的方法

    @annotation(com.example.annotation.Loggable)

  • 结合多个条件:匹配 com.example.service 包中所有被 @Loggable 注解标记的方法

    execution(* com.example.service.*.*(..)) && @annotation(com.example.annotation.Loggable)

  • 有异常抛出的方法:匹配 com.example.service 包下所有方法,并且这些方法抛出 Exception

    execution(* com.example.service.*.*(..)) throws Exception

posted @   CyrusHuang  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示