Spring @Around注解使用及说明

 更新时间:2025年12月26日 08:36:00   作者:百***5588  
@Around是SpringAOP中的一个注解,用于定义环绕通知,可以在方法执行前后执行自定义逻辑,并控制方法的执行或修改返回值, SpringAOP通过代理对象实现环绕通知,匹配切入点,创建代理并执行环绕通知,@Around注解的应用场景广泛

@Around是 Spring AOP(面向切面编程)中的一个注解,它用于定义一个环绕通知(Around Advice)。

环绕通知是 AOP 中最强大的一种通知类型,因为它能够在方法执行之前和之后都执行自定义的逻辑,并且可以控制方法是否继续执行或改变其返回值。

@Around注解的基本用法

要使用@Around注解,你需要先定义一个切面(Aspect),然后在该切面中使用@Around注解来标注一个方法,该方法将作为环绕通知。环绕通知方法必须接受一个ProceedingJoinPoint类型的参数,这个参数提供了对正在执行的方法的访问。

以下是一个简单的例子:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAroundAdvice {

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
        // 在方法执行之前的逻辑
        System.out.println("Before method execution");

        try {
            Object result = pjp.proceed(); // 执行目标方法
            // 在方法执行之后的逻辑
            System.out.println("After method execution");
            return result; // 返回目标方法的执行结果
        } catch (Throwable throwable) {
            // 处理异常
            System.out.println("Exception occurred: " + throwable.getMessage());
            throw throwable; // 重新抛出异常
        }
    }
}

@Around注解的工作机制

  1. 匹配切入点@Around注解的值是一个切入点表达式(Pointcut Expression),它指定了哪些方法将被这个环绕通知拦截。在上面的例子中,切入点表达式"execution(* com.example.service.*.*(..))"匹配了com.example.service包下所有类的所有方法。

  2. 创建代理:Spring AOP 会在运行时为匹配到的方法创建代理对象。当这些方法被调用时,实际上调用的是代理对象的方法。

  3. 执行环绕通知:当代理对象的方法被调用时,Spring AOP 会先执行环绕通知中的逻辑。在环绕通知中,你可以通过调用**ProceedingJoinPointproceed**方法来执行目标方法。你也可以选择不调用proceed方法,从而阻止目标方法的执行。

  4. 处理返回值和异常:环绕通知可以获取目标方法的返回值,并在必要时进行修改。同时,它也可以捕获目标方法抛出的异常,并进行相应的处理。

以下是一些常见的@Around注解应用场景:

  1. 日志记录:在目标方法执行之前和之后记录日志,可以帮助开发者了解方法的执行流程、输入参数、返回值以及执行时间等信息。这对于调试和监控应用程序的状态非常有帮助。

  2. 性能监控:通过在目标方法执行前后记录时间戳,可以计算出方法的执行时间。这对于性能优化和瓶颈识别非常重要,可以帮助开发者找出需要优化的代码段。

  3. 事务管理:在目标方法执行之前开启一个事务,并在方法执行成功后提交事务;如果方法执行失败,则回滚事务。这样可以确保数据的一致性和完整性。

  4. 缓存管理:在目标方法执行之前检查缓存中是否存在所需的数据;如果存在,则直接返回缓存中的数据,避免重复执行耗时的方法;如果不存在,则执行方法并将结果存入缓存中。

  5. 权限检查:在目标方法执行之前检查当前用户是否具有执行该方法的权限;如果没有权限,则抛出异常或返回错误提示,从而保护系统的安全性。

  6. 异常处理:捕获目标方法抛出的异常,并进行统一处理,如记录异常日志、发送报警通知或返回友好的错误提示给用户。这可以提高系统的健壮性和用户体验。

  7. 输入参数校验:在目标方法执行之前对输入参数进行校验,确保参数的有效性和合法性。如果参数无效或不合法,则抛出异常或返回错误提示,避免执行无效的操作。

  8. 结果后处理:在目标方法执行之后对返回结果进行后处理,如格式化数据、转换数据类型或添加额外的信息。这可以满足不同的业务需求和数据展示要求。

综上所述,@Around注解在Spring AOP中具有广泛的应用场景,它能够帮助开发者在不修改目标方法代码的情况下实现各种复杂的功能和逻辑。通过合理地使用@Around注解,可以提高代码的可读性、可维护性和可扩展性。

@Around 注解常用场景实例

权限校验

以下是一个使用@Around注解进行权限校验的示例代码:

@Around("@annotation(authCheck)")
public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
    String mustRole = authCheck.mustRole();
    RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
    HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
    User loginUser = userService.getLoginUser(request);
    if (!loginUser.hasRole(mustRole)) {
        throw new AccessDeniedException("用户没有权限执行此操作");
    }
    return joinPoint.proceed(); // 继续执行目标方法
}

在这个示例中,doInterceptor方法会在被@AuthCheck注解标记的方法执行前后运行。首先检查用户是否有足够的权限,如果没有权限则抛出异常,否则继续执行目标方法。

日志记录和性能监控

以下是一个使用@Around注解的具体实例,该实例展示了如何在Spring AOP中实现日志记录和性能监控的功能。

首先,我们需要定义一个切面类,并在其中使用@Around注解来标注环绕通知方法。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAndPerformanceAspect {

    @Around("execution(* com.example.service.*.*(..))")
    public Object logAndMeasureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录方法开始执行的时间
        long startTime = System.currentTimeMillis();

        // 记录日志:方法开始执行
        System.out.println("Method " + joinPoint.getSignature().getName() + " is starting with arguments: " + Arrays.toString(joinPoint.getArgs()));

        try {
            // 执行目标方法
            Object result = joinPoint.proceed();

            // 记录方法执行结束的时间
            long endTime = System.currentTimeMillis();

            // 记录日志:方法执行结束,并输出执行时间
            System.out.println("Method " + joinPoint.getSignature().getName() + " executed in " + (endTime - startTime) + " milliseconds with result: " + result);

            // 返回目标方法的执行结果
            return result;
        } catch (Throwable throwable) {
            // 记录异常日志
            System.out.println("Exception occurred in method " + joinPoint.getSignature().getName() + ": " + throwable.getMessage());

            // 重新抛出异常,以便上层调用者处理
            throw throwable;
        }
    }
}

在这个例子中,LoggingAndPerformanceAspect是一个切面类,它包含了一个使用@Around注解标注的环绕通知方法logAndMeasureExecutionTime。这个方法会在匹配到的方法执行之前和之后分别记录日志,并测量方法的执行时间。

接下来,我们需要确保Spring容器能够识别这个切面类,并将其应用到相应的目标方法上。通常,这可以通过在Spring配置文件中启用AOP自动代理或者通过@EnableAspectJAutoProxy注解来实现。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {

    // 其他Bean定义...

    // 确保LoggingAndPerformanceAspect被Spring容器管理
    @Bean
    public LoggingAndPerformanceAspect loggingAndPerformanceAspect() {
        return new LoggingAndPerformanceAspect();
    }
}

现在,当Spring容器中的任何匹配到切入点表达式"execution(* com.example.service.*.*(..))"的方法被执行时,logAndMeasureExecutionTime环绕通知都会被触发,从而记录日志和测量执行时间。

例如,如果你有一个服务类MyService,其中有一个方法doSomething,那么当这个方法被调用时,你会在控制台看到类似以下的输出:

Method doSomething is starting with arguments: [...]
Method doSomething executed in XXX milliseconds with result: ...

这样,你就成功地使用@Around注解实现了日志记录和性能监控的功能。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • intellij idea查看方法被哪些类引用过(推荐)

    intellij idea查看方法被哪些类引用过(推荐)

    这篇文章主要介绍了intellij idea查看方法被哪些类引用过,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java中@EnableAutoConfiguration注解使用

    java中@EnableAutoConfiguration注解使用

    在Spring Boot框架中,@EnableAutoConfiguration是一种非常重要的注解,本文就来介绍一下java中@EnableAutoConfiguration注解使用,感兴趣的可以了解一下
    2023-11-11
  • Spring 开发过程中Value 注解的使用场景

    Spring 开发过程中Value 注解的使用场景

    这篇文章主要介绍了Spring 开发过程中Value 注解的使用场景,帮助大家更好的理解和使用spring框架,感兴趣的朋友可以了解下
    2020-11-11
  • maven打生产环境可执行包的实现

    maven打生产环境可执行包的实现

    本文主要介绍了maven打生产环境可执行包的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • java按字节截取带有汉字的字符串的解法(推荐)

    java按字节截取带有汉字的字符串的解法(推荐)

    下面小编就为大家带来一篇java按字节截取带有汉字的字符串的解法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • 计算机二级考试java软件操作教程 教大家如何学习java

    计算机二级考试java软件操作教程 教大家如何学习java

    如何成为一名知识丰富的Java程序员,顺利通过计算机二级Java考试,这篇文章主要主要教大家如何学习java,java的学习路线是什么,从何学起,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Java解析XML(4种方式)案例详解

    Java解析XML(4种方式)案例详解

    这篇文章主要介绍了Java解析XML(4种方式)案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • springboot项目不同环境的配置读取方式

    springboot项目不同环境的配置读取方式

    SpringBoot支持application.properties、application.yml、application.yaml三种配置文件类型,可同时存在并合并配置,配置文件的读取优先级为:application.properties > application.yml > application.yaml,不同位置的相同类型配置文件
    2024-11-11
  • springboot中缩短一个url链接的实现

    springboot中缩短一个url链接的实现

    缩短 URL 是现代应用程序中常见的需求,通常用于减少长 URL 的长度,使其更易于分享,URL 缩短服务的核心思路是将长 URL 映射到一个唯一的短代码,本文主要介绍了springboot中缩短一个url链接的实现,感兴趣的可以了解一下
    2024-09-09
  • mybatis-plus如何修改日志只打印SQL语句不打印查询结果

    mybatis-plus如何修改日志只打印SQL语句不打印查询结果

    这篇文章主要介绍了mybatis-plus如何修改日志只打印SQL语句不打印查询结果问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06

最新评论