AOP-实现步骤 & 切入点表达式语法

![[Pasted image 20251003194032.png]]

切入点表达式语法

@Pointcut 的值是切入点表达式,用于匹配目标方法。常用语法有:

1. execution():最常用,按方法签名匹配

语法:execution(修饰符 返回值 包名.类名.方法名(参数) 异常)

通配符:

  • *:匹配任意字符(如任意返回值、任意方法名)
  • ..:匹配任意层级的包或任意参数(如 com.example..* 表示 com.example 下所有子包)

示例:

1
2
3
4
5
6
7
8
// 匹配 com.example.service 包下所有类的 public 方法
@Pointcut("execution(public * com.example.service.*.*(..))")

// 匹配 com.example.dao 包及子包下所有类的任意方法(返回值为 String)
@Pointcut("execution(String com.example.dao..*.*(..))")

// 匹配 UserService 类中参数为 (String, int) 的方法
@Pointcut("execution(* com.example.service.UserService.*(String, int))")

2. within():按类 / 包匹配(比 execution 更粗粒度)

1
2
3
4
5
// 匹配 com.example.service 包下所有类的所有方法
@Pointcut("within(com.example.service.*)")

// 匹配 com.example.service 包及子包下所有类的所有方法
@Pointcut("within(com.example.service..*)")

3. @annotation():按方法上的注解匹配

1
2
// 匹配所有标注了 @Log 注解的方法(自定义注解)
@Pointcut("@annotation(com.example.annotation.Log)")

4. args():按方法参数类型匹配

1
2
3
4
5
// 匹配第一个参数为 String 类型的方法
@Pointcut("args(String, ..)")

// 匹配参数类型为 User 且有 @Valid 注解的方法
@Pointcut("args(@javax.validation.Valid com.example.entity.User)")

5. bean():按 Spring 容器中的 Bean 名称匹配

1
2
3
4
5
// 匹配名称为 "userService" 的 Bean 的所有方法
@Pointcut("bean(userService)")

// 匹配名称以 "Service" 结尾的 Bean 的所有方法
@Pointcut("bean(*Service)")

组合切入点

通过逻辑运算符(&&||!)组合多个切入点:

1
2
3
4
5
6
7
// 匹配 service 包中且标注了 @Log 的方法
@Pointcut("within(com.example.service..*) && @annotation(com.example.annotation.Log)")
public void serviceWithLog() {}

// 匹配 service 包或 dao 包中的方法
@Pointcut("within(com.example.service..*) || within(com.example.dao..*)")
public void serviceOrDao() {}

关键点

  • @Pointcut 必须定义在切面类@Aspect 标注的类)中。
  • 切入点方法的访问修饰符通常为 public,返回值为 void,方法名自定义(作为引用标识)。
  • 表达式优先级:execution > within > bean(从细到粗),按需选择合适的粒度。

通过 @Pointcut 可以清晰、灵活地定义需要增强的目标方法,是 AOP 中 “面向切面” 思想的核心实现。