跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Spring通知类型
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Spring通知类型 = '''Spring AOP(面向切面编程)'''提供了多种通知(Advice)类型,允许开发者在不修改原有业务逻辑代码的情况下,通过声明式方式在方法执行的不同阶段插入横切关注点(如日志、事务管理等)。本文将详细介绍Spring AOP中的五种通知类型及其应用场景。 == 通知类型概述 == 通知是AOP的核心概念之一,它定义了“何时”以及“做什么”。Spring AOP支持以下五种通知类型: 1. '''前置通知(Before Advice)''':在目标方法执行前执行。 2. '''后置通知(After Returning Advice)''':在目标方法成功执行后执行(无异常抛出时)。 3. '''异常通知(After Throwing Advice)''':在目标方法抛出异常后执行。 4. '''最终通知(After (Finally) Advice)''':在目标方法执行后执行(无论是否抛出异常)。 5. '''环绕通知(Around Advice)''':包围目标方法的执行,可以控制是否执行目标方法以及修改返回值。 以下是一个通知执行顺序的示意图: <mermaid> sequenceDiagram participant Client participant Proxy participant Target Client->>Proxy: 调用方法 alt 环绕通知(前置部分) Proxy->>Proxy: 执行环绕通知的前置逻辑 end alt 前置通知 Proxy->>Proxy: 执行前置通知 end Proxy->>Target: 执行目标方法 alt 后置通知(成功时) Target-->>Proxy: 返回结果 Proxy->>Proxy: 执行后置通知 end alt 异常通知(失败时) Target--xProxy: 抛出异常 Proxy->>Proxy: 执行异常通知 end alt 最终通知 Proxy->>Proxy: 执行最终通知 end alt 环绕通知(后置部分) Proxy->>Proxy: 执行环绕通知的后置逻辑 end Proxy-->>Client: 返回结果或异常 </mermaid> == 详细说明与示例 == === 1. 前置通知(Before Advice) === 在目标方法执行前触发,适用于权限检查、参数验证等场景。 <syntaxhighlight lang="java"> @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void beforeAdvice(JoinPoint joinPoint) { System.out.println("前置通知:准备执行 " + joinPoint.getSignature().getName()); } } </syntaxhighlight> '''输出示例:''' <pre> 前置通知:准备执行 getUserById </pre> === 2. 后置通知(After Returning Advice) === 仅在目标方法成功执行后触发,可访问返回值。 <syntaxhighlight lang="java"> @AfterReturning( pointcut = "execution(* com.example.service.*.*(..))", returning = "result" ) public void afterReturningAdvice(JoinPoint joinPoint, Object result) { System.out.println("后置通知:方法 " + joinPoint.getSignature().getName() + " 执行成功,返回值: " + result); } </syntaxhighlight> '''输出示例:''' <pre> 后置通知:方法 getUserById 执行成功,返回值: User{id=1, name='John'} </pre> === 3. 异常通知(After Throwing Advice) === 当目标方法抛出异常时触发,适合异常日志记录。 <syntaxhighlight lang="java"> @AfterThrowing( pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex" ) public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) { System.err.println("异常通知:方法 " + joinPoint.getSignature().getName() + " 抛出异常: " + ex.getMessage()); } </syntaxhighlight> '''输出示例:''' <pre> 异常通知:方法 updateUser 抛出异常: 用户不存在 </pre> === 4. 最终通知(After (Finally) Advice) === 无论目标方法是否成功完成都会执行,类似于try-catch-finally中的finally块。 <syntaxhighlight lang="java"> @After("execution(* com.example.service.*.*(..))") public void afterFinallyAdvice(JoinPoint joinPoint) { System.out.println("最终通知:方法 " + joinPoint.getSignature().getName() + " 执行结束"); } </syntaxhighlight> '''输出示例(成功时):''' <pre> 最终通知:方法 getUserById 执行结束 </pre> '''输出示例(异常时):''' <pre> 最终通知:方法 updateUser 执行结束 </pre> === 5. 环绕通知(Around Advice) === 功能最强大的通知类型,可以完全控制目标方法的执行。 <syntaxhighlight lang="java"> @Around("execution(* com.example.service.*.*(..))") public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("环绕通知-前置:准备执行 " + joinPoint.getSignature().getName()); try { Object result = joinPoint.proceed(); // 执行目标方法 System.out.println("环绕通知-后置:方法执行成功,返回值: " + result); return result; } catch (Exception ex) { System.err.println("环绕通知-异常:捕获异常: " + ex.getMessage()); throw ex; } finally { System.out.println("环绕通知-最终:方法执行结束"); } } </syntaxhighlight> '''输出示例:''' <pre> 环绕通知-前置:准备执行 getUserById 环绕通知-后置:方法执行成功,返回值: User{id=1, name='John'} 环绕通知-最终:方法执行结束 </pre> == 实际应用案例 == === 性能监控场景 === 通过环绕通知实现方法执行时间统计: <syntaxhighlight lang="java"> @Around("execution(* com.example.service.*.*(..))") public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long elapsedTime = System.currentTimeMillis() - startTime; System.out.println("方法 " + joinPoint.getSignature().getName() + " 执行耗时: " + elapsedTime + "ms"); return result; } </syntaxhighlight> === 事务管理场景 === 结合声明式事务使用环绕通知: <syntaxhighlight lang="java"> @Around("@annotation(org.springframework.transaction.annotation.Transactional)") public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { Object result = joinPoint.proceed(); transactionManager.commit(status); return result; } catch (Exception ex) { transactionManager.rollback(status); throw ex; } } </syntaxhighlight> == 数学表达 == 在AOP中,通知的执行可以形式化表示为: <math> \begin{cases} Before(f) & \text{当 } f \text{ 被调用前执行} \\ AfterReturning(f, r) & \text{当 } f \text{ 成功返回 } r \text{ 后执行} \\ AfterThrowing(f, e) & \text{当 } f \text{ 抛出异常 } e \text{ 后执行} \\ After(f) & \text{无论 } f \text{ 如何结束都执行} \\ Around(f) & \text{完全控制 } f \text{ 的执行流程} \end{cases} </math> == 总结 == Spring AOP的通知类型为开发者提供了灵活的横切关注点处理能力。通过合理组合这些通知,可以实现: * 非侵入式的功能增强 * 清晰的职责分离 * 可复用的通用逻辑 建议初学者从简单的'''前置通知'''和'''后置通知'''开始实践,逐步掌握更复杂的'''环绕通知'''应用。 [[Category:后端框架]] [[Category:Spring]] [[Category:Spring AOP]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)