Spring 切面执行链的实现示例

 更新时间:2025年10月19日 10:52:24   作者:wx6875a567c49bb  
在实际应用中,一个方法通常会被多个切面拦截,本文主要介绍了Spring 切面执行链的实现示例,具有一定的参考价值,感兴趣的可以了解一下

在实际应用中,一个方法通常会被多个切面拦截。例如,我们有一个方法,既需要记录其执行日志,又需要应用一些安全限制。这类职责通常由专门的切面来处理,因此在该场景下,会有两个切面作用于同一个方法的执行过程。同时使用多个切面没有任何问题,但有时切面的执行顺序非常重要,因为有些切面会控制切入点方法的执行,比如鉴权的切面在鉴权失败后便不会继续执行切入点方法。这种情况下其他切面可能就没有机会执行了。

// UserService.java
@Service
public class UserService {

  private final Logger logger = Logger.getLogger(UserService.class.getName());

  @ToLog
  public String getUser(String username) throws Exception {
    logger.info("getUser method called with username: " + username);
    return username;
  }
}

// LoggingAspect.java
// 定义日志切面
@Aspect
public class LoggingAspect {

  // 定义日志记录器
  private final Logger logger = Logger.getLogger(LoggingAspect.class.getName());

  // 定义日志环绕通知
  @Around("@annotation(dev.xyz.annotation.ToLog)")
  public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    // 切入点方法执行前执行
    logger.info("Logging before method: " + joinPoint.getSignature().getName());
    // 执行切入点方法
    Object result = joinPoint.proceed();
    // 切入点方法执行后执行
    logger.info("Logging after method: " + joinPoint.getSignature().getName());
    // 修改切入点方法的返回值
    return result;
  }
}

// SecurityAspect.java
// 定义鉴权切面
@Aspect
public class SecurityAspect {

  private final Logger logger = Logger.getLogger(SecurityAspect.class.getName());

  @Around("@annotation(dev.xyz.annotation.ToLog)")
  public Object checkSecurity(ProceedingJoinPoint joinPoint) throws Throwable {
    logger.info("Security check performed.");
    // 这里模拟鉴权失败
    if (joinPoint.getArgs()[0].equals("Mark")) {
      throw new Exception("Security check failed.");
    }
    Object result = joinPoint.proceed();
    logger.info("Security check passed.");
    return result;
  }
}

// ProjectConfig.java
// Spring 配置,创建两个切面 bean
@Configuration
@ComponentScan(basePackages = "dev.xyz.service")
@EnableAspectJAutoProxy
public class ProjectConfig {

  @Bean
  SecurityAspect securityAspect() {
    return new SecurityAspect();
  }

  @Bean
  LoggingAspect loggingAspect() {
    return new LoggingAspect();
  }
}

// Main.java
// 在 main 方法中进行测试
public class Main {
    public static void main(String[] args) throws Exception {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProjectConfig.class);

        UserService userService = context.getBean(UserService.class);
        userService.getUser("Mark");
    }
}

这里先执行了 SecurityAspect 切面,因为鉴权失败,所以 LoggingAspect 切面不会执行。

这种情况下,可以使用 @Order 注解来控制切面执行的顺序,给注解传递一个数值作为参数,数值越小越先执行,现在给切面类添加上 @Order 注解,让 LoggingAspect 先于 SecurityAspect 执行:

// LoggingAspect.java
// 定义日志切面
@Aspect
@Order(1)
public class LoggingAspect {

	// 这里的代码不变
  // ...
}

// SecurityAspect.java
// 定义鉴权切面
@Aspect
public class SecurityAspect {

	// 这里的代码不变
  // ...
}

现在结果变的不一样了,先执行了 LoggingAspect 切面:

如果存在多个 @Order 数值一样的切面,这时的结果又和不使用 @Order 一样了。不使用 @Order 注解的切面永远晚于使用 @Order 注解的切面执行。

到此这篇关于Spring 切面执行链的实现示例的文章就介绍到这了,更多相关Spring 切面执行链内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot 项目如何在tomcat容器中运行的实现方法

    SpringBoot 项目如何在tomcat容器中运行的实现方法

    这篇文章主要介绍了SpringBoot 项目如何在tomcat容器中运行的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • SpringBoot整合SpringDataRedis的示例代码

    SpringBoot整合SpringDataRedis的示例代码

    这篇文章主要介绍了SpringBoot整合SpringDataRedis的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 解析SpringBoot中@Autowire注解的实现原理

    解析SpringBoot中@Autowire注解的实现原理

    在开发Java项目时,依赖注入是一种常见的实现方式,SpringBoot框架通过@Autowired注解来实现依赖注入的功能,本文将介绍SpringBoot中 Autowired注解实现的原理
    2023-06-06
  • spring boot使用@Async异步注解的实现原理+源码

    spring boot使用@Async异步注解的实现原理+源码

    通常我们都是采用多线程的方式来实现上述业务功能,但spring 提供更优雅的方式来实现上述功能,就是@Async 异步注解,在方法上添加@Async,spring就会借助AOP,异步执行方法,接下来通过本文给大家介绍spring boot异步注解的相关知识,一起看看吧
    2021-06-06
  • mybatis映射器配置小结

    mybatis映射器配置小结

    本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • 从HelloWorld和文档注释开始入门Java编程

    从HelloWorld和文档注释开始入门Java编程

    这篇文章主要介绍了从HelloWorld和文档注释开始入门Java编程,涉及到Javadoc工具的使用,需要的朋友可以参考下
    2015-10-10
  • minio安装部署及使用的详细过程

    minio安装部署及使用的详细过程

    MinIO是一个基于Apache License v2.0开源协议的对象存储服务,下面这篇文章主要给大家介绍了关于minio安装部署及使用的详细过程,文中通过实例代码以及图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • Java实现简单抽奖功能界面

    Java实现简单抽奖功能界面

    这篇文章主要为大家详细介绍了Java实现简单抽奖功能界面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • 关于JDK15的新特性之TextBlocks文本块的引入和使用

    关于JDK15的新特性之TextBlocks文本块的引入和使用

    这篇文章主要介绍了关于JDK15的新特性之文本块的引入和使用,如果具有一种语言学机制,可以比多行文字更直观地表示字符串,而且可以跨越多行,而且不会出现转义的视觉混乱,那么这将提高广泛Java类程序的可读性和可写性,需要的朋友可以参考下
    2023-07-07
  • java实现电脑定时关机的方法

    java实现电脑定时关机的方法

    这篇文章主要介绍了java实现电脑定时关机的方法,首先通过java注册windows服务程序,再以一个简单的java程序实现定时关机的功能,非常具有实用价值,需要的朋友可以参考下
    2014-11-11

最新评论