SpringAOP+自定义注解简单使用

一、SpringAOP简述


SpringAOP可以帮助我们在不修改源代码的前提下实现功能增强,其底层实现原理基于Java动态代理或者CGLIB。

在这里插入图片描述

之前我们使用 execution表达式指定被AOP增强的方法:(execution关键字用于描述哪些方法需要切面逻辑)

在这里插入图片描述

但是这样使用非常不灵活,因为并不是Service中所有的方法都需要被增强。

其实我们可以参考Spring声明式事务注解@Transactional,在项目中利用自定义注解实现了大量共性需求。


SpringAOP+自定义注解的应用场景:

  • 收集上报指定关键方法的入参、执行时间、返回结果等关键信息,用作后期调优处理;
  • 关键方法在幂等性前置校验(基于本地消息表);
  • 类似于Spring-Retryt模块,提供关键方法多次调用重试机制;
  • 提供关键方法自定义的快速熔断、服务降级等职责;
  • 关键方法的共性入参校验、权限校验;
  • 关键方法在执行后的扩展行为,例如记录日志、启动其他任务等;

二、SpringAOP+自定义注解使用


1、创建springboot工程,在pom.xml中引入aspectjweaver依赖

<!-- AOP切面编程框架 -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <!--<version>1.9.4</version>-->
</dependency>

2、编写自定义注解(使用@interface关键字定义注解)

package cn.baidou.dianping.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义方法注解
 */
// @Target(ElementType.METHOD) 用来约束这个自定义注解只能用在方法上
@Target(ElementType.METHOD)
// @Retention 用来控制注解的生命周期,RUNTIME表示这个注解一直存活 (作用在源码阶段,字节码文件阶段,运行阶段)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodExporter {
    
    

}

3、编写切面类

package cn.baidou.dianping.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 获取目标入参、执行时间、执行过程、返回结果等细节并打印到日志上
 *
 * @author 白豆五
 * @version 2023/06/15
 * @since JDK8
 */
@Aspect //设置当前类为切面类
@Component //配置成Spring管理的bean
@Slf4j
public class MethodExporterAspect {
    
    
    
    /*
        @Around:环绕通知,最强大的通知类型,可以控制方法入参、执行、返回结果等各方面细节
        "@annotation(xxx.MethodExporter)":表示任何添加@MethodExporter注解的目标方法都将在执行方法前先执行该切面方法
     */
    @Around("@annotation(cn.baidou.dianping.annotation.MethodExporter)")
    public Object methodExporter(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
        long startTime = System.currentTimeMillis();//开始时间
        Object proceed = joinPoint.proceed();      // 执行目标方法,获取方法返回值
        long endTime = System.currentTimeMillis(); //结束时间

        ObjectMapper mapper = new ObjectMapper();

        // 将入参JSON序列化
        String jsonParam = mapper.writeValueAsString(joinPoint.getArgs());//joinPoint.getArgs()获取目标方法的参数

        // 将返回结果JSON序列化
        String jsonResult = null;
        if (jsonResult != null) {
    
    
            jsonResult = mapper.writeValueAsString(proceed);//mapper.writeValueAsString()可用于将任何Java值序列化为字符串
        } else {
    
    
            jsonResult = "null";
        }

        // 模拟上报过程
        log.debug("正在上报服务器调用过程:\ntarget:{}.{}()\nexecution:{}ms,\nparameter:{}\nresult:{}",
                joinPoint.getTarget().getClass().getSimpleName(),
                joinPoint.getSignature().getName(),
                (endTime - startTime),
                jsonParam,
                jsonResult);

        return proceed;
    }
}

4、编写测试代码

package cn.baidou.dianping.controller;

import cn.baidou.dianping.annotation.MethodExporter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author 白豆五
 * @version 2023/06/15
 * @since JDK8
 */
@RestController
@RequestMapping("/test")
public class TestController {
    
    

    @MethodExporter
    @GetMapping("/list")
    public Map test() {
    
    
        Map resultMap = new LinkedHashMap();
        resultMap.put("code", "200");
        resultMap.put("message", "ok");

        try {
    
    
            TimeUnit.SECONDS.sleep(new Random().nextInt(10));
        } catch (InterruptedException e) {
    
    
            throw new RuntimeException(e);
        }
        return resultMap;
    }
}

5、重启项目,测试接口

在这里插入图片描述

控制台输出:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46921028/article/details/131237613