跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Spring后置通知(After Advice)
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Spring后置通知(After Advice) = == 概述 == '''Spring后置通知(After Advice)'''是Spring AOP(面向切面编程)中的一种通知类型,它在目标方法执行'''之后'''触发,无论目标方法是否成功执行或抛出异常。后置通知通常用于执行清理操作、日志记录或结果处理等任务。 后置通知与前置通知(Before Advice)和返回通知(After Returning Advice)不同,它不关心目标方法的返回值或异常状态,仅确保在方法执行后执行特定逻辑。 == 核心特性 == * '''执行时机''':目标方法执行后(包括正常返回和异常抛出) * '''不依赖返回值''':无论方法是否成功都会执行 * '''常见用途''':资源清理、审计日志、监控统计 == 实现方式 == Spring提供两种主要方式实现后置通知: === 1. 基于XML配置 === <syntaxhighlight lang="xml"> <aop:config> <aop:aspect id="afterExample" ref="aspectBean"> <aop:after pointcut="execution(* com.example.service.*.*(..))" method="doAfter"/> </aop:aspect> </aop:config> </syntaxhighlight> === 2. 基于注解 === <syntaxhighlight lang="java"> @Aspect @Component public class LoggingAspect { @After("execution(* com.example.service.*.*(..))") public void afterAdvice(JoinPoint joinPoint) { System.out.println("方法执行完成: " + joinPoint.getSignature().getName()); } } </syntaxhighlight> == 代码示例 == 以下完整示例展示后置通知的实际应用: === 服务类 === <syntaxhighlight lang="java"> public class PaymentService { public void processPayment(String account, double amount) { System.out.println("Processing payment of $" + amount + " to " + account); // 模拟业务逻辑 if(amount <= 0) { throw new IllegalArgumentException("金额必须大于零"); } } } </syntaxhighlight> === 切面配置 === <syntaxhighlight lang="java"> @Aspect @Component public class PaymentAspect { @After("execution(* com.example.service.PaymentService.processPayment(..))") public void afterPayment(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); System.out.printf("[审计日志] 支付操作已执行 - 账户: %s, 金额: %.2f%n", args[0], args[1]); } } </syntaxhighlight> === 测试用例 === <syntaxhighlight lang="java"> @SpringBootTest public class PaymentServiceTest { @Autowired private PaymentService paymentService; @Test void testNormalPayment() { paymentService.processPayment("user123", 100.0); // 控制台输出: // Processing payment of $100.0 to user123 // [审计日志] 支付操作已执行 - 账户: user123, 金额: 100.00 } @Test void testInvalidPayment() { assertThrows(IllegalArgumentException.class, () -> { paymentService.processPayment("user123", -50.0); }); // 控制台输出: // Processing payment of $-50.0 to user123 // [审计日志] 支付操作已执行 - 账户: user123, 金额: -50.00 } } </syntaxhighlight> == 执行流程 == <mermaid> sequenceDiagram participant Client participant Proxy participant Target participant Aspect Client->>Proxy: 调用目标方法 Proxy->>Target: 转发调用 Target-->>Proxy: 方法执行(正常/异常) Proxy->>Aspect: 执行后置通知 Aspect-->>Proxy: 通知完成 Proxy-->>Client: 返回结果/异常 </mermaid> == 实际应用场景 == '''1. 数据库连接释放''' 确保在任何情况下都释放数据库连接,避免连接泄漏 '''2. 操作审计日志''' 记录用户操作,无论操作成功与否 '''3. 接口监控''' 统计方法调用次数和执行时间 '''4. 资源清理''' 如临时文件删除、缓存清除等 == 注意事项 == * 后置通知'''无法'''阻止异常传播(如需处理异常应使用@AfterThrowing) * 后置通知中无法访问返回值(如需处理返回值应使用@AfterReturning) * 多个后置通知的执行顺序可通过@Order注解控制 == 数学表达 == 后置通知的执行时机可以表示为: <math> T_{after} = T_{execution} + \Delta t </math> 其中: * <math>T_{after}</math> 是后置通知执行时间点 * <math>T_{execution}</math> 是目标方法执行完成时间点 * <math>\Delta t</math> 是AOP框架开销时间 == 高级主题 == 对于需要更精细控制的场景,可以组合使用多种通知类型: <syntaxhighlight lang="java"> @Aspect public class ComprehensiveAspect { @Before("execution(* com.example..*(..))") public void before(JoinPoint jp) { /* 前置逻辑 */ } @After("execution(* com.example..*(..))") public void after(JoinPoint jp) { /* 后置逻辑 */ } @AfterReturning(pointcut="execution(* com.example..*(..))", returning="result") public void afterReturning(JoinPoint jp, Object result) { /* 返回后逻辑 */ } @AfterThrowing(pointcut="execution(* com.example..*(..))", throwing="ex") public void afterThrowing(JoinPoint jp, Exception ex) { /* 异常处理逻辑 */ } } </syntaxhighlight> 这种组合方式可以实现完整的横切关注点处理,满足企业级应用的需求。 [[Category:后端框架]] [[Category:Spring]] [[Category:Spring AOP]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)