深入理解Spring AOP 编程之切入点表达式详解

一、概念部分

1.切入点表达式

  切入点表达式(Pointcut Expressions)是 Spring AOP 中用于定义切面的切入点逻辑的关键语法。它通过精确描述程序中的哪些连接点(Join Point)需要执行通知逻辑,决定了 AOP 的应用范围。

切入点表达式常与通知类型配合使用,用于描述如下信息:

  • 目标方法的修饰符

  • 返回类型

  • 包名与类名

  • 方法名

  • 参数类型和个数

  • 异常类型

2. 切入点表达式的常见语法

语法格式如下:

execution([修饰符] 返回值 包名.类名.方法名(参数) [throws 异常类型])

其中:

  • [修饰符] 可以省略(如 publicprotected

  • 返回值 支持通配符 * 表示任意返回值

  • 包名类名方法名 可以使用通配符匹配部分内容

  • (参数) 支持 * 表示任意参数

  • throws 部分可以省略

3. 常见通配符的含义

  • *单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分。

  • ..多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

  • &&||!:用于组合表达式,分别表示逻辑与、逻辑或、逻辑非

二、示例代码解读

@Slf4j
@Component
@Aspect
public class MyAspect2 {

    @Before("execution(public void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    @Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    @Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(*))")
    @Before("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @Before("execution(* com.itheima.service.impl.*.*(..))")
    @Before("execution(* com.itheima.service.impl.DeptServiceImpl.del*(..))")

    @Before("execution(* com..service.*.*(..))")
    @Before("execution(* *(..))") //慎用!!!!!!!!!! --- 性能越差

    @Before("execution(* com.itheima.service.impl.DeptServiceImpl.list()) ||  " +
            "execution(* com.itheima.service.impl.DeptServiceImpl.save(*))")

    @Before("execution(* com.itheima.service.DeptService.*(..))") //切入点表达式可以基于接口进行匹配
    @Before("execution(public void com.itheima.service.impl.DeptServiceImpl.delete(..))")
    @Before("@annotation(com.itheima.anno.Log)")
    public void before(){
        log.info("MyAspect2 -> before ...");
    }
}

1. 注解解读

  • @Slf4j:由 Lombok 提供的日志注解,生成 log 对象。

  • @Component:将该类声明为 Spring 容器中的一个组件。

  • @Aspect:声明该类为切面类,启用 AOP 功能。

  • @Before:声明前置通知,目标方法在执行前触发 before() 方法。

2. 切入点表达式分析

精确匹配
execution(public void com.itheima.service
          .impl.DeptServiceImpl.delete(java.lang.Integer)) 
  • 精确匹配 DeptServiceImpl 类中的 delete 方法,该方法的签名必须完全一致。

省略修饰符匹配
execution(void com.itheima.service.impl
          .DeptServiceImpl.delete(java.lang.Integer))
  •  忽略访问修饰符(publicprotectedprivate),匹配范围放宽。

参数通配符匹配
execution(void com.itheima.service.impl.DeptServiceImpl.delete(*)) 
  • 匹配 delete 方法,允许参数为任意类型的单个参数

方法名称通配符匹配
execution(* com.itheima.service.impl.DeptServiceImpl.del*(..)) 
  • 匹配 DeptServiceImpl 类中所有以 del 开头的方法,参数数量与类型不限

包与类的通配符匹配
execution(* com.itheima.service.impl.*.*(..)) 
  • 匹配 impl 包下所有类的所有方法,参数数量与类型不限。

execution(* com..service.*.*(..))
  • 匹配 com 包及其子包下所有类的所有方法。

基于注解匹配
@annotation(com.itheima.anno.Log) 
  • 匹配所有标注了 @Log 注解的方法。

组合条件匹配
execution(* com.itheima.service.impl.DeptServiceImpl.list()) 
            || execution(* com.itheima.service.impl.DeptServiceImpl.save(*))
  • 使用逻辑运算符 || 组合表达式,匹配 list 方法或 save 方法,同时需要注意方法的参数匹配规则。list 方法必须无参,而 save 方法可以接受单个任意类型的参数。

三、总结部分

书写建议

  • 所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:findXxxupdateXxx

  • 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。

  • 在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名尽量不使用 ..,使用 * 匹配单个包。

  1. 切入点表达式的核心作用

    • 用于定义 AOP 的目标范围。

    • 支持多种匹配方式(精确匹配、通配符匹配、基于注解等)。

    • 结合逻辑运算符,可实现复杂的业务逻辑需求。

  2. 常见场景与注意事项

    • 精确匹配适用于特定方法的切入逻辑。

    • 包与类的通配符匹配适用于模块级别的切面应用。

    • 基于注解的匹配方式更灵活,减少了与方法签名的强耦合。

    • 全局匹配(如 execution(* *(..)))慎用,可能导致性能问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值