详解SpringBoot AOP 拦截器(Aspect注解方式)

下面是详解 SpringBoot AOP 拦截器(Aspect 注解方式)的完整攻略,并附带两条示例。

什么是 AOP

AOP(Aspect Oriented Programming,面向切面编程)是一种面向对象编程的编程思想,AOP 的思想是将系统分解为多个功能单元,称之为“切面”(Aspect),然后编写代码来定义这些切面。这些切面可以跨越多个类,不仅仅是某个类的某个方法。AOP 主要用于解决系统中的横切关注点(Crosscutting Concerns)问题,比如日志记录、性能统计、安全控制、事务处理等。

什么是 SpringBoot AOP 拦截器(Aspect 注解方式)

SpringBoot AOP 在 AOP 基础上,采用了拦截器的方式来实现对方法的切面编程。SpringBoot AOP 拦截器可以根据注解设置来实现不同的切面,常见的切面有:

  • @Before:在方法之前执行。
  • @After:在方法之后执行。
  • @AfterReturning:在方法正常返回之后执行。
  • @AfterThrowing:在方法抛出异常之后执行。

SpringBoot AOP 拦截器(Aspect 注解方式)的实现步骤

下面是 SpringBoot AOP 拦截器(Aspect 注解方式)的实现步骤:

步骤一:创建一个自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

步骤二:编写 AOP 切面代码

@Aspect
@Component
@Slf4j
public class LogAspect {
    @Around("@annotation(com.example.demo.annotation.Log)")
    public Object logRecord(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = null;
        try {
            // 方法执行前
            String className = proceedingJoinPoint.getTarget().getClass().getName();
            String methodName = proceedingJoinPoint.getSignature().getName();
            log.info("Class Name: {}, Method Name:{}", className, methodName);
            Object[] args = proceedingJoinPoint.getArgs();
            for (Object arg : args) {
                log.info("Args: {}", arg);
            }
            result = proceedingJoinPoint.proceed(args);
            // 方法正常返回
            log.info("Result:{}", result);
        } catch (Throwable throwable) {
            // 方法执行异常
            log.error("Method Execution Error:{}", throwable.getMessage());
            throw throwable;
        }
        return result;
    }
}

步骤三:在需要切面的方法上添加自定义注解

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @Log(value = "查询用户信息")
    @GetMapping("/user/get/{id}")
    public UserVO getUserById(@PathVariable("id") Long id) {
        return userService.getUserById(id);
    }
}

示例一:记录用户操作日志

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserOperateLog {
    String value() default "";
}

@Aspect
@Component
@Slf4j
public class UserOperateLogAspect {
    @Autowired
    private UserOperateLogService userOperateLogService;

    @Around("@annotation(com.example.demo.annotation.UserOperateLog)")
    public Object userOperateLogRecord(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = null;
        try {
            // 方法执行前
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            UserOperateLog userOperateLogAnn = signature.getMethod().getAnnotation(UserOperateLog.class);
            String operation = userOperateLogAnn.value();
            String className = proceedingJoinPoint.getTarget().getClass().getName();
            String methodName = proceedingJoinPoint.getSignature().getName();
            log.info("Class Name: {}, Method Name:{}, Operation: {}", className, methodName, operation);

            // 记录用户操作日志
            User user = SessionUtils.getCurrentUser();
            if (user != null) {
                UserOperateLog userOperateLog = new UserOperateLog();
                userOperateLog.setUserId(user.getId());
                userOperateLog.setUserName(user.getName());
                userOperateLog.setOperation(operation);
                userOperateLog.setOperateTime(new Date());
                userOperateLogService.saveUserOperateLog(userOperateLog);
            }

            Object[] args = proceedingJoinPoint.getArgs();
            result = proceedingJoinPoint.proceed(args);
            // 方法正常返回
            log.info("Result:{}", result);
        } catch (Throwable throwable) {
            // 方法执行异常
            log.error("Method Execution Error:{}", throwable.getMessage());
            throw throwable;
        }
        return result;
    }
}

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @UserOperateLog(value = "查询用户信息")
    @GetMapping("/user/get/{id}")
    public UserVO getUserById(@PathVariable("id") Long id) {
        return userService.getUserById(id);
    }
}

示例二:时间统计

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeCount {
    String value() default "";
}

@Aspect
@Component
@Slf4j
public class TimeCountAspect {

    @Around("@annotation(com.example.demo.annotation.TimeCount)")
    public Object timeCount(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = null;
        try {
            // 方法执行前
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            TimeCount timeCountAnn = signature.getMethod().getAnnotation(TimeCount.class);
            String operation = timeCountAnn.value();
            long startTime = System.currentTimeMillis();
            result = proceedingJoinPoint.proceed();
            long endTime = System.currentTimeMillis();
            log.info("Operation: {},TimeCost: {}ms", operation, endTime - startTime);
        } catch (Throwable throwable) {
            // 方法执行异常
            log.error("Method Execution Error:{}", throwable.getMessage());
            throw throwable;
        }
        return result;
    }
}

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @TimeCount(value = "查询用户信息")
    @GetMapping("/user/get/{id}")
    public UserVO getUserById(@PathVariable("id") Long id) {
        return userService.getUserById(id);
    }
}

以上就是详解 SpringBoot AOP 拦截器(Aspect 注解方式)的完整攻略以及两条示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解SpringBoot AOP 拦截器(Aspect注解方式) - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java lambda循环_使用Java 8 Lambda简化嵌套循环操作

    下面是关于Java 8 Lambda简化嵌套循环操作的攻略: 1. lambda表达式简介 Java 8引入了lambda表达式,它是一种匿名函数,可以像参数一样传递给方法或赋值给变量。在使用lambda表达式时只需要关注其输入和输出,而不必关心具体的实现细节,这让代码变得更加简洁易读。 2. 简化循环操作 在Java 8之前,嵌套循环操作可能会使代码显得冗…

    Java 2023年5月26日
    00
  • Java面试题冲刺第十八天–Spring框架3

    Java面试题冲刺第十八天–Spring框架3 简介 本文是Java面试题冲刺系列的第十八篇,主要介绍Spring框架的知识点,包括Spring框架的特点、Spring框架中常用组件、Spring的优点等。 Spring框架的特点 Spring框架是一个轻量级的开源JavaEE框架,由于其具有以下特点而备受开发者欢迎: 依赖注入(DI)和控制反转(IoC)…

    Java 2023年5月19日
    00
  • 如何基于js及java分析并封装排序算法

    当前前端开发中,排序算法是比较基础的内容,经常会在算法学习和面试中出现。本文将介绍如何基于js及java分析并封装排序算法,为学习和使用排序算法提供帮助。 1. 排序算法介绍 在计算机科学中,排序算法是一种将一串数据按照指定的顺序进行排列的方法。常见的排序算法包括冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序等等。 2. 分析与封装 要实现排序算…

    Java 2023年5月19日
    00
  • 微信小程序后端Java接口开发的详细步骤

    下面是微信小程序后端Java接口开发的详细步骤: 准备工作 在微信公众平台注册小程序,并获取小程序的 AppID。 在小程序后台设置服务器域名以及接口请求白名单。 在服务器上安装 JDK、Tomcat、Maven,并启动 Tomcat 服务。 选择适合自己的 Spring Boot 或者其他 Java 后端框架。 开发过程 创建项目:使用 Maven 创建项…

    Java 2023年5月23日
    00
  • 垃圾回收的作用是什么?

    以下是关于垃圾回收的作用的完整使用攻略: 垃圾回收的作用 垃圾回收是一种自动化的内存管理方式,它的作用在程序运行过程中,自动回收不再使用的内存空间,从而避免内存泄漏和内存溢出。垃圾收可以减少程序员的工作量,提高程序的可靠性和安全性。 以下是两个示例说明垃圾回收的作用 1. 避免内存泄漏 存泄漏是指程序在运行过程中,分配的内存空间没有及时释放,致内存空间的浪费…

    Java 2023年5月12日
    00
  • java多态实现电子宠物系统

    实现电子宠物系统可以使用Java多态的特性,以下是完整攻略: 一、电子宠物系统的基本要求 电子宠物系统是模拟一个宠物的生命周期,包括喂食、玩耍、睡觉、生病等多种状态。系统需要实现以下功能: 宠物属性:宠物的名字、体力、饥饿值等属性; 宠物动作:宠物可以吃食物、玩耍、睡觉、生病、死亡等; 宠物状态:宠物会根据不同的状态进行不同的动作,例如当它饥饿时就会吃食物。…

    Java 2023年5月24日
    00
  • Java全面解析string类型的xml字符串

    要解析含有XML标签的字符串,可以使用Java中自带的解析API——DOM(文档对象模型),或者第三方的解析库——JDOM、DOM4J等。下面以DOM为例,提供一份Java全面解析string类型的XML字符串的攻略。 1. 准备字符串 假设有一个字符串xmlString,它包含以下XML标签: <person> <name>Tom&…

    Java 2023年5月27日
    00
  • Java程序开发环境配置图文教程

    下面我将为您讲解“Java程序开发环境配置图文教程”的完整攻略。 环境要求 在开始配置Java程序开发环境前,请确保您的电脑已经安装好了以下环境: 操作系统:Windows/macOS/Linux Java开发工具包(Java Development Kit,简称JDK) 集成开发环境(Integrated Development Environment,简…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部