Spring 切入点表达式(Pointcut Expression)

通俗易懂!2025 年最新 Spring 切入点表达式(Pointcut)全攻略
背完这张表 + 口诀,面试手写切面随便秒,大厂随便进!

一张图记住所有语法(面试30秒画完满分版)

execution(  修饰符  返回值类型  包名.类名.方法名(参数)  throws异常 )
execution(  public   *      com.example.service..*.*(..)        )
     ↑        ↑       ↑           ↑        ↑     ↑      ↑
     可省    可*    可*      关键..   可*   可*   任意参数

2025 年真实项目最常用的 10 种写法(直接抄就行)

排名写法意思(大白话)真实使用场景
1execution(* com.example.controller..*.*(..))所有 controller 包下的所有类的所有方法统一日志、统一异常处理
2execution(* com.example.service..*Service.*(..))所有 Service 包下以 Service 结尾的所有方法事务、缓存、分布式锁
3execution(* com.example.service.UserService.*(..))只有 UserService 的所有方法精确控制某个核心服务
4execution(* com.example.controller.*Controller.save*(..))所有 Controller 里以 save 开头的方法防重复提交
5execution(* com.example.service..*(..) throws BusinessException)所有 Service 方法抛业务异常的统一捕获业务异常
6@annotation(org.springframework.transaction.annotation.Transactional)加了 @Transactional 注解的方法二次增强事务(比如打印事务耗时)
7@annotation(com.example.annotation.NoRepeatSubmit)加了自定义 @NoRepeatSubmit 注解的方法防重点击
8within(com.example.controller..*)controller 包下的所有类(包括子包)和 execution 差不多,稍微粗糙一点
9execution(* com.example.service..*.*(..)) && @annotation(org.springframework.web.bind.annotation.GetMapping)Service 里加了 @GetMapping 的方法(几乎不用)基本没人这么写
10execution(* com..*.*(..)) && args(String,..)第一个参数是 String 的所有方法参数匹配(很少用)

常用通配符 + 符号全解(背3分钟,终身不忘)

通配符意思例子
*匹配任意字符*Service → UserService、OrderService
..匹配任意层级包com..service → com.service / com.a.b.service
..匹配任意参数*(..) → 0个、1个、多个参数都行
+匹配子类com.example.service.BaseService+
&&并且execution + annotation
||或者execution A 或 execution B
!取反!execution(* com.example.service.Admin*.*(..))

2025 大厂最爱用的组合写法(直接抄进项目)

@Aspect
@Component
public class AllInOneAspect {

    // 1. 所有 Controller(最常用)
    @Pointcut("execution(* com.example.controller..*.*(..))")
    private void controller() {}

    // 2. 所有 Service(事务、缓存、锁)
    @Pointcut("execution(* com.example.service..*Service.*(..))")
    private void service() {}

    // 3. 加了自定义注解 @NoRepeatSubmit 的方法
    @Pointcut("@annotation(com.example.annotation.NoRepeatSubmit)")
    private void noRepeat() {}

    // 4. 加了 @Cacheable 的方法(用于打印缓存命中率)
    @Pointcut("@annotation(org.springframework.cache.annotation.Cacheable)")
    private void cacheable() {}

    // 组合用法:所有 Controller + 加了 @NoRepeatSubmit 的方法
    @Before("controller() || noRepeat()")
    public void doBefore(JoinPoint jp) {
        log.info("请求来了:{}", jp.getSignature());
    }
}

面试终极 6 连问 + 标准答案(背完无敌)

  1. ..* 区别是什么?
    答:.. 匹配任意层级包或任意参数,* 只匹配一层或一个名字。
  2. 怎么切“所有加了 @Transactional 的方法”?
    答:@annotation(org.springframework.transaction.annotation.Transactional)
  3. 怎么切“所有以 save 开头的方法”?
    答:execution(* *(..).save*(..))execution(* com..*.save*(..))
  4. within 和 execution 区别?
    答:within 是按“类”匹配,execution 是按“方法”精确匹配,execution 更精准。
  5. 想切“所有有 String 参数的方法”怎么写?
    答:execution(* *(*,String,..))args(String,..)
  6. 怎么排除某个包不被切?
    答:execution(* com.example..*.*(..)) && !execution(* com.example.controller.admin..*.*(..))

终极记忆口诀(10秒背完所有语法)

“execution 包..类.方法(参数)
星号通配一层,点点通配全部
@annotation 切注解最牛
&& 或 || ! 组合随便揉!”

背完这张表 + 10个常用写法 + 口诀,
面试官让你“手写一个切所有 Controller 的 Pointcut”,
你10秒写完 + 顺便甩出 @annotation 高级玩法,
他当场就说:“这小伙子切点玩得飞起!”
现在你已经可以轻松手撕任何横切需求了(日志、事务、权限、防重、限流、缓存)一把梭!冲!

文章已创建 3958

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部