springboot中使用aop实现方法拦截处理

2023-12-13 06:18:35

在spring中,很多功能和特性的实现都是基于aop切面来实现的,比如事务功能、异步处理、代理等。在spring框架中也已经给我们提供了面向切面编程的功能,通过几个注解就可以完成。
要使用spring提供的aop功能,首先需要引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

在编写一个实现类,在这个类中添加aop相关的注解实现web接口请求到响应的耗时:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.example.pojo.ApiResult;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.stereotype.Component;

/**
 * 应用切面类
 *
 * @author xingo
 * @date 2023/12/12
 */
@Aspect
@Component
@ConditionalOnWebApplication
public class AopAspect {

    // 通过环绕通知方式处理
    /**
     * 定义切入点
     */
    @Pointcut("execution(* org.example.controller.*.*(..))")
    public void pointcut() {

    }

    /**
     * 环绕通知
     * @param pj
     * @return
     */
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint pj) throws Throwable {
        long start = System.currentTimeMillis();

        // 执行目标方法
        Object result = pj.proceed();
        if(result == null) {
            return result;
        }

        long diff = System.currentTimeMillis() - start;
        if(result instanceof ApiResult) {
            ApiResult temp = (ApiResult) result;
            temp.setTime(diff);
        }
        System.out.println("请求耗时 ====>>> " + diff);

        return result;
    }

    // 通过前置通知和后置通知方式处理
//    /**
//     * 请求开始时间
//     */
//    public static final ThreadLocal<Long> threadStartTime = new ThreadLocal<>();
//
//    /**
//     * 前置通知:执行目标方法之前运行
//     * @param jp
//     */
//    @Before("execution(* org.example.controller.*.*(..))")
//    public void beforeMethod(JoinPoint jp) {
//        threadStartTime.set(System.currentTimeMillis());
//    }
//
//    /**
//     * 返回通知:目标方法正常返回值后运行
//     * @param jp
//     */
//    @AfterReturning(value = "execution(* org.example.controller.*.*(..))", returning = "result")
//    public void aftherReturn(JoinPoint jp, Object result) {
//        long diff = System.currentTimeMillis() - threadStartTime.get();
//        threadStartTime.remove();
//        System.out.println("请求耗时 ====>>> " + diff);
//        if(result instanceof ApiResult) {
//            ApiResult temp = (ApiResult) result;
//            temp.setTime(diff);
//        }
//    }
//
//    /**
//     * 异常通知:目标方法出现异常后运行
//     * @param jp
//     */
//    @AfterThrowing(value = "execution(* org.example.controller.*.*(..))", throwing = "e")
//    public void afterThrowing(JoinPoint jp, Exception e) {
//        e.printStackTrace();
//        long diff = System.currentTimeMillis() - threadStartTime.get();
//        threadStartTime.remove();
//        System.out.println("请求耗时 ====>>> " + diff);
//    }

//    /**
//     * 后置通知:目标方法运行结束之后,不管有没有异常
//     * @param jp
//     */
//    @After("execution(* org.example.controller.*.*(..))")
//    public void afterMethod(JoinPoint jp) {
//        long diff = System.currentTimeMillis() - threadStartTime.get();
//        threadStartTime.remove();
//        System.out.println("请求耗时 ====>>> " + diff);
//    }
}

上面是对 org.example.controller 包下以及所有子包下的类和方法进行拦截,统计方法调用耗时。该功能可以有两种方式实现:一种是使用环绕通知实现;另一种是通过前置通知和后置通知方式实现。
spring中通过aop可以实现很多功能,可以在某些方法执行前后做一些加强操作,记录方法处理日志,做权限拦截等等。总之可以通过使用aop避免写一些重复代码,让开发者更关注业务逻辑开发。

文章来源:https://blog.csdn.net/dream_xin2013/article/details/134942045
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。