@Pointcut的核心作用是定义可复用的切点表达式,通过声明无参void空方法作为命名切点,在通知中直接引用方法名实现复用、组合及跨切面共享,提升可维护性与类型安全性。

在 Spring AOP 中,`@Pointcut` 的核心作用就是**定义可复用的切点表达式**,避免在多个通知(`@Before`、`@After` 等)里重复写相同的 `execution()` 或其他表达式。
用 `@Pointcut` 声明命名切点
你只需在一个 `@Aspect` 类中,用 `@Pointcut` 注解定义一个无参、返回 void 的空方法,方法名就成为切点的“别名”:
@Aspect
public class LoggingAspect {
@Pointcut("execution(* com.example.service..*.*(..))")
public void serviceLayer() {} // 切点名:serviceLayer
<pre class='brush:java;toolbar:false;'>@Pointcut("execution(* com.example.controller..*.*(..))")
public void controllerLayer() {}}
这个方法体为空,Spring 只读取其注解中的表达式,不执行方法本身。
立即学习“Java免费学习笔记(深入)”;
在通知中引用命名切点
后续所有通知都可以直接使用方法名(不带括号)作为切点,语法简洁且类型安全:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
@Before("serviceLayer()") // ✅ 引用上面定义的切点
public void logBeforeService(JoinPoint jp) {
System.out.println("进入 service 方法:" + jp.getSignature());
}
<p>@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void logServiceReturn(Object result) {
System.out.println("service 方法返回:" + result);
}</p><p>@Around("controllerLayer()") // ✅ 复用另一个切点
public Object auditController(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
try {
return pjp.proceed();
} finally {
System.out.println("控制器耗时:" + (System.currentTimeMillis() - start));
}
}组合与重用切点表达式
你可以像搭积木一样组合已有切点,支持 `&&`(and)、`||`(or)、`!`(not)运算符(注意:需用括号包裹子表达式):
-
组合多个切点:
@Pointcut("serviceLayer() && within(com.example.service.impl..*)") -
排除某些方法:
@Pointcut("serviceLayer() && !execution(* *.*Test*(..))") -
共用基础切点:比如定义
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)"),再在多个通知中复用它来拦截所有 `@RequestMapping` 方法
跨切面复用切点(推荐方式)
如果多个 `@Aspect` 类需要共用同一套切点逻辑,建议将公共切点集中定义在一个独立的类中,并设为 `public static`:
public class CommonPointcuts {
@Pointcut("execution(* com.example..service..*.*(..))")
public static void serviceMethods() {}
<pre class='brush:java;toolbar:false;'>@Pointcut("execution(* com.example..repository..*.*(..))")
public static void repositoryMethods() {}}
其他切面直接引用(注意加类名前缀):
@Aspect
public class MetricsAspect {
@Before(CommonPointcuts.class.getName() + ".serviceMethods()")
public void recordServiceTime(JoinPoint jp) { ... }
}这样既解耦又便于维护,修改一处,所有引用自动生效。

















