当前位置: 首页 > article >正文

@Before 和 @Around 在 Spring AOP 中的核心区别

在 Spring AOP 中,@Before@Around 是两种常用的通知(Advice)类型,它们的核心区别主要体现在执行时机、控制能力使用场景上。以下是详细对比:


1. 执行时机

  • @Before
    在目标方法执行前触发,无法影响目标方法的执行流程(无论是否抛出异常,目标方法都会执行)。

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        // 在目标方法执行前执行
    }
    
  • @Around
    在目标方法前后都可以执行代码,并且控制目标方法是否执行。需要显式调用 ProceedingJoinPoint.proceed() 来触发目标方法。

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        // 方法执行前
        Object result = pjp.proceed(); // 触发目标方法
        // 方法执行后
        return result;
    }
    

2. 控制能力

  • @Before

    • 无法阻止目标方法的执行(即使 @Before 抛出异常,目标方法仍会执行)。
    • 无法修改目标方法的返回值。
  • @Around

    • 可以决定是否执行目标方法(通过是否调用 proceed())。
    • 可以修改目标方法的输入参数(通过 proceed(args))。
    • 可以修改目标方法的返回值(通过修改 proceed() 的返回结果)。
    • 可以捕获并处理目标方法的异常(通过 try-catch 包裹 proceed())。

3. 参数类型

  • @Before
    接收 JoinPoint 参数,用于获取连接点信息(如方法名、参数等)。

  • @Around
    必须接收 ProceedingJoinPoint 参数(继承自 JoinPoint),并通过 proceed() 触发目标方法。


4. 典型使用场景

  • @Before
    适用于轻量级操作,例如:

    • 记录方法调用日志。
    • 参数校验(但无法终止方法执行)。
    • 设置上下文环境(如开启事务)。
  • @Around
    适用于需要完全控制目标方法执行流程的场景,例如:

    • 性能监控(统计方法执行时间)。
    • 权限校验(校验失败时直接返回,不执行目标方法)。
    • 缓存逻辑(直接返回缓存结果,跳过目标方法)。
    • 异常包装(捕获异常并返回自定义错误信息)。

5. 性能开销

  • @Around 的性能开销通常高于 @Before,因为它需要维护方法执行的上下文和控制流程。如果无需控制目标方法的执行,优先使用 @Before

示例对比

// 使用 @Before:仅在方法前执行,无法阻止方法
@Before("execution(* com.example.service.*.*(..))")
public void logStart(JoinPoint jp) {
    System.out.println("Method starts: " + jp.getSignature().getName());
}

// 使用 @Around:控制方法执行并统计耗时
@Around("execution(* com.example.service.*.*(..))")
public Object measureTime(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.currentTimeMillis();
    Object result = pjp.proceed(); // 必须显式调用
    long time = System.currentTimeMillis() - start;
    System.out.println("Method took: " + time + "ms");
    return result;
}

总结

特性@Before@Around
执行时机方法执行前方法执行前后
控制目标方法无法控制可控制(通过 proceed()
修改返回值不支持支持
参数类型JoinPointProceedingJoinPoint
异常处理无法捕获目标方法异常可捕获并处理异常
适用场景简单前置操作需要控制流程或修改结果的复杂逻辑

根据需求选择合适的注解:

  • 若只需在方法执行前插入逻辑,使用 @Before
  • 若需要控制方法执行、修改参数/返回值或处理异常,使用 @Around

http://www.kler.cn/a/585100.html

相关文章:

  • 蓝桥杯备考:新二叉树
  • 【视频】ffmpeg、Nginx搭建RTMP、HLS服务器
  • 【菜鸟飞】通过vsCode用python访问公网deepseek-r1等模型(Tocken模式)
  • 使用服务器如何DNS呢
  • cgi,php-cgi,fastcgi,php-fpm,nginx 小记
  • 打造独一无二的 CI/CD 工厂:Java 应用的自动化之旅
  • 247g 的工业级电调,如何让无人机飞得更 “聪明“?——STONE 200A-M 深度测评
  • Apache POI详解
  • 跟网型逆变器小干扰稳定性分析与控制策略优化simulink仿真模型和代码(包含完整仿真报告)
  • 破解“光伏+储能+充电”一体化难题!安科瑞全方案打造智慧能源新标杆
  • 动态IP vs 静态IP:终极对比一览表
  • 解决 Linux /dev/mapper/ubuntu--vg-ubuntu--lv 磁盘空间不足的问题
  • 开目三维焊接工艺规划与仿真软件 3DWELD
  • 使用git reset --hard FETCH_HEAD后如何恢复
  • Python数据类型进阶——详解
  • 47.HarmonyOS NEXT 登录模块开发教程(二):一键登录页面实现
  • 【机器人-开发工具】ROS 2 (2)Ubuntu20.04安装ROS 2 Foxy版本
  • 代码比较功能
  • Kafka精选面试题
  • firewall的使用