AOP - 切点表达式
execution 表达式
// 语法格式
execution(方法访问修饰符? 方法返回类型 方法所在包路径?.方法名(方法参数类型) 方法抛出的异常?)
-
访问修饰符:public、protected、private 等,可省略,省略表示任意修饰符
// com.example.service.UserService 类中的所有 public 方法 execution(public * com.example.service.UserService.*(..))
-
返回类型:指方法返回类型,可以是具体的类名,比如 String、void、com.example.User 等,
*
表示任何类型 -
包路径:可选部分,指定方法所在的类或接口的模式。可以是具体的类名、接口名或
*
表示任意包,..
表示子包// 指定类下所有方法作为切点(UserService 类中的所有方法) execution(* com.example.service.UserService.*(..)) // 指定接口所有实现类的方法作为切点(UserServiceInterface 接口的所有类中的方法) execution(* com.example.service.UserServiceInterface.*(..)) // 指定子类所有方法作为切点(+表示 BaseService 类及其所有子类的方法) execution(* com.example.service.BaseService+.*(..)) // 指定 com.example.service 包及其子包下所有类的方法作为切点(com.example.service 包及其子包中的所有方法) execution(* com.example.service..*.*(..))
-
方法名:方法名称,
*
表示任何方法 -
方法参数:指方法参数类型,
..
表示任意数量的参数,*
表示任意类型// com.example.service.UserService 类中的 addUser 方法(第一个参数为 String 类型,其余参数可以是任意类型) execution(* com.example.service.UserService.addUser(String, ..)) // 第一个参数为 String 类型,第二个参数为 Integer 类型,其余参数可以是任意类型 execution(* com.example.service.UserService.addUser(String, Integer ..))
-
异常:方法抛出的异常,可选项
// com.example.service.UserService 类下抛出 Exception 的所有方法 execution(* com.example.service.UserService.*(..) throws Exception)
within 表达式
execution 完全可以代替 within 的功能
*表示任意类,.. 表示子包和的所有类(..* 和 .. 是相同功能只是语义上有些许着重的意思 )
// 语法格式(指定类或包,不能具体到方法级别)
within(范围)
-
匹配特定的类
// 匹配 UserService 类中的所有方法 within(com.example.service.UserService)
-
匹配特定的包
// com.example.service 这个包及其子包下的所有类 within(com.example.service..*) // 选择的切点是一样的 within(com.example.service..)
@annotation 表达式
这也是比较常用的表达式,语法也比较简单
// 标注了 @GetMapping 的方法将作为切点
@annotation(org.springframework.web.bind.annotation.GetMapping)
其他表达式
除了 execution、within、@annotation 表达式之外还有 this、target、args 表达式,不过这三种不常用
组合表达式
// AND
@Pointcut("execution(* com.example.service.*(..)) && within(com.example.service.UserService)")
// OR
@Pointcut("execution(* com.example.service.*(..)) || execution(* com.example.repository.*(..))")
// NOT
@Pointcut("execution(* com.example.service.*(..)) && !execution(* com.example.service.UserService.*(..))")
表达式示例
-
某个特殊的方法:com.example.service.UserService 类中所有以 find 开头的公共方法
execution(public * com.example.service.UserService.find*(..))
-
类中的所有方法:com.example.service 包下所有类的所有方法
execution(* com.example.service.*.*(..))
-
特定参数类型的方法:com.example.service.UserService 类中接受一个 User 对象作为参数的方法
execution(String com.example.service.UserService.getName(..))
-
com.example.service 包及其子包下的所有类中的所有方法
execution(* com.example.service..*.*(..))
-
com.example.service 包及其子包下的所有类中的所有方法
within 不能指定某个方法,本身是类级别的;execution 可以指定某个方法
如果exection 切某个包及其子包下所有方法就和 within 功能一样了
within(com.example.service..*)
-
带有特定注解的方法:被 @Loggable 注解标记的方法
@annotation(com.example.annotation.Loggable)
-
结合多个条件:匹配 com.example.service 包中所有被 @Loggable 注解标记的方法
execution(* com.example.service.*.*(..)) && @annotation(com.example.annotation.Loggable)
-
有异常抛出的方法:匹配 com.example.service 包下所有方法,并且这些方法抛出 Exception
execution(* com.example.service.*.*(..)) throws Exception
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)