java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Aop @After使用场景

一文详解Spring Aop @After(后置通知)的使用场景

作者:冰糖心书房

@After 是 Spring AOP 中的另一种通知(Advice)类型,通常被称为“后置通知”或“最终通知”,本文将通过详细的代码示例给大家介绍一下Spring Aop @After(后置通知)的使用场景,需要的朋友可以参考下

核心定义

@After 是 Spring AOP 中的另一种通知(Advice)类型,通常被称为“后置通知”或“最终通知”。

它的核心作用是:

无论目标方法是正常执行完成,还是在执行过程中抛出了异常,@After 通知中的代码 总是 会在目标方法执行之后被执行。

最经典的类比就是 Java 中的 try...catch...finally 语句块里的 finally 部分。@After 的行为和 finally 块的行为几乎一模一样。

@After 通知的执行流程

为了更好地理解,我们来看两种情况下的执行顺序:

情况一:目标方法成功执行

情况二:目标方法抛出异常

一个非常关键的点是:@After 通知本身无法访问目标方法的返回值(因为它可能根本没有返回值,比如抛异常时),也无法捕获或处理从目标方法中抛出的异常。它只是一个保证“最后一定会被执行”的钩子。

@After 通知能做什么?(主要应用场景)

后置通知非常适合执行那些必须进行的“清理”或“收尾”工作,无论业务逻辑成功与否。

资源释放 (Resource Cleanup)

上下文清理 (Context Cleanup)

最终日志记录 (Final Auditing)

性能监控 (Performance Monitoring)

示例:

与 @AfterReturning 和 @AfterThrowing 的区别

这是新手很容易混淆的地方,理解它们的区别至关重要:

知类型执行时机能否访问返回值?能否访问异常?主要用途
@After (最终通知)总是在目标方法后执行(无论成功或失败)不能不能资源清理、最终日志
@AfterReturning (返回通知)仅在目标方法成功执行后执行可以不适用基于返回结果的附加操作
@AfterThrowing (异常通知)仅在目标方法抛出异常后执行不适用可以异常日志记录、告警通知

简单来说:

代码示例

我们扩展之前的例子,增加一个删除方法(可能会失败),并为所有方法添加 @After 通知。

1. 业务服务类 (目标对象)

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    // 成功执行的例子
    public String findUserById(Long id) {
        System.out.println("--- 核心业务逻辑:正在根据 ID 查询用户... ---");
        return "User" + id;
    }

    // 抛出异常的例子
    public void deleteUser(Long id) {
        System.out.println("--- 核心业务逻辑:正在尝试删除用户... ---");
        if (id <= 0) {
            throw new IllegalArgumentException("用户ID无效,删除失败!");
        }
        System.out.println("用户 " + id + " 已被成功删除。");
    }
}

2. 切面类 (Aspect) 中定义 @After 通知

package com.example.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Aspect
@Component
public class LoggingAspect {

    @Pointcut("execution(public * com.example.service.*.*(..))")
    public void serviceLayerPointcut() {}

    // 前置通知
    @Before("serviceLayerPointcut()")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("==================================================");
        System.out.printf("[AOP 前置通知]: 方法 [%s] 即将执行... 参数: %s%n", methodName, Arrays.toString(args));
    }

    // 后置通知 (最终通知)
    @After("serviceLayerPointcut()")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.printf("[AOP 后置通知]: 方法 [%s] 执行完毕。执行清理工作...%n", methodName);
        System.out.println("--------------------------------------------------\n");
    }
}

3. 运行代码并观察输出

调用成功的方法 userService.findUserById(101L):

==================================================
[AOP 前置通知]: 方法 [findUserById] 即将执行... 参数: [101]
--- 核心业务逻辑:正在根据 ID 查询用户... ---
[AOP 后置通知]: 方法 [findUserById] 执行完毕。执行清理工作...
--------------------------------------------------

@After 在方法成功后执行了。

调用失败的方法 userService.deleteUser(0L) (需要用 try-catch 捕获异常):

try {
    userService.deleteUser(0L);
} catch (Exception e) {
    System.err.println("在调用方捕获到异常: " + e.getMessage());
}

输出:

==================================================
[AOP 前置通知]: 方法 [deleteUser] 即将执行... 参数: [0]
--- 核心业务逻辑:正在尝试删除用户... ---
[AOP 后置通知]: 方法 [deleteUser] 执行完毕。执行清理工作...
--------------------------------------------------

在调用方捕获到异常: 用户ID无效,删除失败!

即使 deleteUser 抛出了异常,@After 通知 (logAfter 方法) 依然被执行了,完美地展示了其 finally 的特性。

总结

特性描述
执行时机无论成功或失败,总是在目标方法执行之后执行。
核心用途资源释放上下文清理、最终日志记录等收尾工作。
行为类似Java 的 finally 语句块。
关键限制无法访问目标方法的返回值,也无法捕获或修改异常。
关键参数可以注入 JoinPoint 对象,获取方法元数据。

以上就是一文详解Spring Aop @After(后置通知)的使用场景的详细内容,更多关于Spring Aop @After使用场景的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文