📍切入点表达式常见形式速查手册
🎯execution(最常用)
语法模板
execution(修饰符?返回类型 包名.类名.方法名(参数)异常?)可以使用通配符描述切入点
- “ * ” :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
- … :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
常用形式
1. 按包匹配
// 精确包匹配execution(*com.example.service.*.*(..))// service包下所有类的方法execution(*com.example.service..*.*(..))// service包及其子包下所有方法// 多级包匹配execution(*com..service.*.*(..))// 任意父包下的service包2. 按类匹配
// 精确类匹配execution(*com.example.service.UserService.*(..))// UserService所有方法// 按类名模式匹配execution(*com.example.service.*Service.*(..))// 以Service结尾的类execution(*com.example.service.*Impl.*(..))// 以Impl结尾的类3. 按方法名匹配
// 精确方法名execution(*com.example.service.UserService.save(..))// 特定方法// 模式匹配方法名execution(*com.example.service.*.save*(..))// 以save开头的方法execution(*com.example.service.*.*User(..))// 以User结尾的方法execution(*com.example.service.*.get*())// 无参的getter方法execution(*com.example.service.*.set*(*))// 单个参数的setter方法4. 按参数匹配
// 精确参数execution(*com.example.service.*.*(String,int))// 参数为(String, int)// 参数模式execution(*com.example.service.*.*(*))// 单个任意参数execution(*com.example.service.*.*(*,*))// 两个任意参数execution(*com.example.service.*.*(*,String))// 第二个参数为Stringexecution(*com.example.service.*.*(..,String))// 最后一个参数为Stringexecution(*com.example.service.*.*(java.lang.String))// 明确指定类型execution(*com.example.service.*.*(com.example.User))// 自定义类型参数5. 按返回类型匹配
execution(voidcom.example.service.*.*(..))// 返回void的方法execution(Stringcom.example.service.*.*(..))// 返回String的方法execution(List<*>com.example.service.*.*(..))// 返回List的方法execution(*com.example.service.*.*(..))// 任意返回值🏷️@annotation(基于注解)
形式
// 匹配方法上的注解@annotation(org.springframework.transaction.annotation.Transactional)@annotation(com.example.annotation.Log)@annotation(com.example.annotation.Cacheable)// 组合使用@annotation(com.example.annotation.Log)&&execution(*com.example.service.*.*(..))示例注解
// 自定义注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceLog{Stringvalue()default"";}// 使用@Log("用户操作")publicvoidsaveUser(){...}📦within(按类型)
形式
// 精确类within(com.example.service.UserService)// UserService所有方法// 包级别within(com.example.service.*)// service包下所有类within(com.example.service..*)// service包及其子包下所有类// 接口/实现类within(com.example.service.BaseService+)// BaseService及其实现类🏢@within(按类上的注解)
形式
// 匹配类上有特定注解的所有方法@within(org.springframework.stereotype.Service)// 所有@Service类@within(org.springframework.web.bind.annotation.RestController)// 所有@RestController类@within(com.example.annotation.Secured)// 所有@Secured注解类🧾bean(Spring特有)
形式
// 按Bean名称bean(userService)// 名为userService的Beanbean(*Service)// 以Service结尾的Beanbean(user*)// 以user开头的Beanbean(*Controller)// 以Controller结尾的Beanbean(*ServiceImpl)// 以ServiceImpl结尾的Bean🔗args(按参数类型/注解)
形式
// 按参数类型args(java.lang.String)// 第一个参数是Stringargs(java.lang.String,java.lang.Long)// 第一个String,第二个Longargs(com.example.User,..)// 第一个参数是User,后面任意// 按参数注解@args(javax.validation.Valid)// 参数有@Valid注解@args(com.example.annotation.NotEmpty)// 参数有@NotEmpty注解🔄this/target(按代理/目标类型)
形式
// JDK代理this(com.example.service.UserService)// 代理对象是UserService类型target(com.example.service.UserService)// 目标对象是UserService类型// CGLIB代理(两者相同)this(com.example.service.UserServiceImpl)target(com.example.service.UserServiceImpl)⚡组合表达式
逻辑运算符
// AND (&&)execution(*com.example.service.*.*(..))&&within(com.example.service.*)execution(*com.example.service.*.*(..))&&@annotation(org.springframework.transaction.annotation.Transactional)// OR (||)execution(*com.example.service.*.save*(..))||execution(*com.example.service.*.update*(..))@annotation(com.example.annotation.Log)||@annotation(com.example.annotation.Monitor)// NOT (!)execution(*com.example.service.*.*(..))&&!execution(*com.example.service.*.get*(..))within(com.example.controller.*)&&!@annotation(com.example.annotation.SkipAuth)实际组合示例
// 1. 监控Service层非查询方法@Pointcut("within(@org.springframework.stereotype.Service *) && "+"execution(* *.*(..)) && "+"!execution(* *.get*(..)) && "+"!execution(* *.find*(..)) && "+"!execution(* *.select*(..))")publicvoidserviceWriteOperation(){}// 2. 权限控制:Controller层需要鉴权的方法@Pointcut("within(@org.springframework.web.bind.annotation.RestController *) && "+"(@annotation(org.springframework.web.bind.annotation.PostMapping) || "+" @annotation(org.springframework.web.bind.annotation.PutMapping) || "+" @annotation(org.springframework.web.bind.annotation.DeleteMapping))")publicvoidneedAuthOperation(){}// 3. 数据库操作监控@Pointcut("execution(* com.example.repository.*.*(..)) || "+"execution(* com.example.dao.*.*(..))")publicvoiddatabaseOperation(){}// 4. 排除特定方法@Pointcut("within(com.example.service.*) && "+"!execution(* com.example.service.HealthCheckService.*(..))")publicvoidserviceExcludeHealthCheck(){}📝命名切入点(可复用)
定义
@Aspect@ComponentpublicclassSystemArchitecture{// 1. 分层架构@Pointcut("within(@org.springframework.stereotype.Service *)")publicvoidserviceLayer(){}@Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")publicvoidcontrollerLayer(){}@Pointcut("within(@org.springframework.stereotype.Repository *)")publicvoidrepositoryLayer(){}// 2. 注解定义@Pointcut("@annotation(com.example.annotation.Log)")publicvoidloggable(){}@Pointcut("@annotation(com.example.annotation.Cacheable)")publicvoidcacheable(){}@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")publicvoidtransactional(){}// 3. 组合定义@Pointcut("serviceLayer() && loggable()")publicvoidloggableService(){}@Pointcut("controllerLayer() && transactional()")publicvoidtransactionalController(){}}// 在其他切面中使用@Before("SystemArchitecture.serviceLayer()")publicvoidbeforeService(){...}📊实际开发常用形式总结
| 场景 | 推荐形式 | 示例 |
|---|---|---|
| 全局日志 | within + 注解 | within(@org.springframework.stereotype.Service *) |
| 事务管理 | @annotation | @annotation(org.springframework.transaction.annotation.Transactional) |
| 权限控制 | @annotation + execution | @annotation(com.example.annotation.RequireAuth) |
| 缓存切面 | @annotation | @annotation(com.example.annotation.Cacheable) |
| 性能监控 | execution + 排除 | execution(* com.example.service.*.*(..)) && !execution(* *.get*(..)) |
| 参数校验 | args | args(com.example.dto.*) |
| 异常处理 | within + 包名 | within(com.example.controller..*) |
| 特定Bean | bean | bean(userService) |
🎯按优先级排序
// 执行顺序:从精确到宽泛1.@annotation(com.example.CustomAnnotation)// 最精确2.execution(*com.example.service.UserService.save(..))3.execution(*com.example.service.UserService.*(..))4.within(com.example.service.UserService)5.execution(*com.example.service.*.*(..))6.within(com.example.service.*)// 最宽泛7.execution(**.*(..))⚠️常见错误
错误示例
// ❌ 过于宽泛(影响性能)execution(**.*(..))// ❌ 缺少参数括号execution(*com.example.service.*.*)// ❌ 包路径错误execution(*com.example.*Service.*(..))// 包名中包含通配符// ✅ 正确做法execution(*com.example.service.*Service.*(..))// 类名中包含通配符最佳实践
// 1. 优先使用注解方式@annotation(com.example.annotation.Log)// 2. 精确匹配,避免扫描过多类within(com.example.service..*)// 3. 组合使用,提高可读性@Pointcut("within(com.example.service..*) && "+"@annotation(org.springframework.transaction.annotation.Transactional)")publicvoidtransactionalService(){}🔧调试技巧
1. 查看匹配的方法
@Aspect@ComponentpublicclassDebugAspect{@Before("yourPointcut()")publicvoiddebug(JoinPointjoinPoint){System.out.println("匹配方法: "+joinPoint.getSignature().toShortString());}}2. 测试切入点表达式
// 使用AspectJ工具测试// 下载aspectjweaver,使用ajc编译测试📚速查表
✅ execution - 按方法签名匹配(最灵活) ✅ @annotation - 按方法注解匹配(最常用) ✅ within - 按类型/包匹配 ✅ @within - 按类注解匹配 ✅ bean - 按Spring Bean名称匹配 ✅ args - 按参数类型/注解匹配 ✅ this/target - 按代理/目标类型匹配 ✅ 组合 - 使用&&、||、!组合多个条件💎一句话总结
切入点表达式选择指南:
要精确 → 用@annotation 要批量 → 用within 要灵活 → 用execution 要简单 → 用bean 要组合 → 用逻辑运算符记住:切入点越精确,性能越好,维护越容易!