跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Spring切点表达式
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Spring切点表达式 = '''Spring切点表达式'''(Pointcut Expression)是Spring AOP(面向切面编程)中用于定义在哪些连接点(Join Point)上应用通知(Advice)的核心语法。它通过特定的表达式语言精确匹配目标方法或类,是AOP实现方法拦截的关键技术。 == 基本概念 == 切点表达式基于'''AspectJ切点表达式语言''',Spring对其进行了部分扩展和简化。主要作用包括: * 指定方法执行(如:`execution()`) * 指定类型匹配(如:`within()`) * 组合多个条件(如:`&&`, `||`, `!`) === 表达式组成 === 一个完整的切点表达式通常包含以下部分: <math>\text{Pointcut} = \text{Designator}(\text{Pattern})</math> 其中: * '''Designator''':指示器(如`execution`) * '''Pattern''':匹配模式(如方法签名) == 核心指示器详解 == === 1. execution() === 最常用的指示器,用于匹配方法执行。 '''语法结构''': <syntaxhighlight lang="java"> execution( [修饰符] 返回类型 [类路径].方法名(参数列表) [throws 异常] ) </syntaxhighlight> '''示例''': <syntaxhighlight lang="java"> // 匹配com.example.service包下所有类的public方法 execution(public * com.example.service.*.*(..)) // 匹配UserService中以get开头的方法 execution(* com.example.service.UserService.get*(..)) // 匹配第一个参数为String的所有方法 execution(* *(String, ..)) </syntaxhighlight> === 2. within() === 匹配特定类型(类/接口)内的所有连接点。 '''示例''': <syntaxhighlight lang="java"> // 匹配Service包下的所有类 within(com.example.service.*) // 匹配UserServiceImpl类 within(com.example.service.UserServiceImpl) </syntaxhighlight> === 3. args() === 基于参数类型的匹配。 '''示例''': <syntaxhighlight lang="java"> // 匹配单个String参数的方法 args(String) // 匹配第一个参数为Long的方法 args(Long,..) </syntaxhighlight> == 组合表达式 == 通过逻辑运算符组合多个表达式: {| class="wikitable" |+ 逻辑运算符示例 ! 运算符 !! 示例 !! 说明 |- | <code>&&</code> || <code>execution(* *(..)) && within(com.example..*)</code> || 同时满足两个条件 |- | <code>||</code> || <code>execution(* save*(..)) || execution(* update*(..))</code> || 满足任一条件 |- | <code>!</code> || <code>!within(com.example.test.*)</code> || 排除test包 |} == 特殊语法 == === 通配符使用 === * <code>*</code>:匹配任意字符(除包分隔符外) * <code>..</code>:多重匹配 * 在包路径中:匹配当前包及其子包(如<code>com.example..*</code>) * 在参数列表中:匹配任意数量参数(如<code>(..)</code>) === bean() === Spring特有语法,通过Bean名称匹配: <syntaxhighlight lang="java"> // 匹配ID以Service结尾的Bean bean(*Service) // 排除userService !bean(userService) </syntaxhighlight> == 实际案例 == === 日志切面示例 === <syntaxhighlight lang="java"> @Aspect @Component public class LoggingAspect { // 拦截service包下所有public方法 @Pointcut("execution(public * com.example.service.*.*(..))") private void serviceLayer() {} @Before("serviceLayer()") public void logMethodStart(JoinPoint jp) { String methodName = jp.getSignature().getName(); System.out.println("【开始执行】" + methodName); } } </syntaxhighlight> === 性能监控示例 === <syntaxhighlight lang="java"> @Aspect @Component public class PerformanceAspect { // 组合表达式:public方法且带有@Monitor注解 @Pointcut("execution(public * *(..)) && @annotation(com.example.Monitor)") private void monitoredMethod() {} @Around("monitoredMethod()") public Object measureTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); long duration = System.currentTimeMillis() - start; System.out.println(pjp.getSignature() + "执行耗时:" + duration + "ms"); return result; } } </syntaxhighlight> == 表达式优化建议 == 1. '''精确匹配优先''':避免过度使用通配符 * 推荐:<code>execution(* com.example.service.UserService.*(..))</code> * 不推荐:<code>execution(* *.*(..))</code> 2. '''组合复用''':通过<code>@Pointcut</code>定义可重用的表达式 <syntaxhighlight lang="java"> @Pointcut("within(com.example.service.*)") public void inServiceLayer() {} @Pointcut("execution(* save*(..))") public void saveOperation() {} // 组合使用 @Before("inServiceLayer() && saveOperation()") public void beforeSave() { ... } </syntaxhighlight> 3. '''性能考虑''':<code>bean()</code>表达式执行效率高于<code>execution()</code> == 常见错误 == {| class="wikitable" |+ 错误模式与修正 ! 错误表达式 !! 问题 !! 修正 |- | <code>execution(* *(..))</code> || 拼写错误 || 改为<code>execution</code> |- | <code>execution(public * *(..)</code> || 缺少右括号 || 补全<code>)</code> |- | <code>within(com.example.*)</code> || 不会匹配子包 || 使用<code>com.example..*</code> |} == 高级技巧 == === 注解驱动切点 === 匹配带有特定注解的方法: <syntaxhighlight lang="java"> // 匹配带有@Transactional注解的方法 @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)") public void transactionalMethod() {} // 匹配参数带有@Valid注解的方法 @Pointcut("execution(* *(.., @javax.validation.Valid (*), ..))") public void validParameter() {} </syntaxhighlight> === 动态切点 === 通过条件判断实现运行时决策: <syntaxhighlight lang="java"> @Pointcut("execution(* com.example.dao.*.*(..)) && if()") public static boolean dynamicPointcut(JoinPoint jp) { return System.currentTimeMillis() % 2 == 0; // 条件示例 } </syntaxhighlight> == 可视化理解 == <mermaid> graph TD A[切点表达式] --> B[execution] A --> C[within] A --> D[args] A --> E[annotation] B --> F["execution(* com.example..*(..))"] C --> G["within(com.example.service.*)"] D --> H["args(java.io.Serializable)"] E --> I["@annotation(org.springframework.transaction.annotation.Transactional)"] </mermaid> == 数学表达 == 切点匹配可以形式化为: <math> P(m) = \begin{cases} true, & \text{当方法m满足表达式条件} \\ false, & \text{否则} \end{cases} </math> 多个表达式的组合运算遵循布尔代数规则: <math> P_1(m) \land P_2(m) \Rightarrow \text{AND运算} </math> <math> P_1(m) \lor P_2(m) \Rightarrow \text{OR运算} </math> [[Category:后端框架]] [[Category:Spring]] [[Category:Spring AOP]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)