【总结】SpringBoot AOP 搭配注解的使用

SpringBoot AOP 搭配注解的使用

  • 自定义日志注解
  • AOP 面向切面编程
    • AOP 增强的实现
    • AOP 基本使用

自定义日志注解

创建自定义的日志注解,用于记录日志的操作,注解包含一个记录操作的枚举类

/**
 * 记录操作日志注解
 *
 * @author zqf
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperateLog {

    OperateTypeEnum operateType() default OperateTypeEnum.GET;

}
/**
 * 操作类型枚举类
 *
 * @author zqf
 */
public enum OperateTypeEnum {

    GET(0),
    ADD(1),
    DELETE(2),
    UPDATE(3);

    Integer value;

    private OperateTypeEnum(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return this.value;
    }

}

AOP 面向切面编程

AOP 增强的实现

AOP 可以通过 5 个注解实现在不同的切面对方法进行增强

  • @Before:在目标方法之前执行,可以通过JoinPoint类获取目标方法的方法名以及参数

  • @After:在目标方法之后执行,可以通过JoinPoint类获取目标方法的方法名以及参数,即使目标方法出错产生异常也会执行该注解标注的方法逻辑

  • @AfterReturning:当目标方法正常执行并返回时,执行该方法,若抛出异常则不执行该方法

  • @AfterThrowing:当目标方法抛出异常时执行该方法,若目标方法正常执行则不会这姓该方法逻辑

  • @Round:环绕方法,在目标方法执行的前后进行逻辑增强

AOP 基本使用

构造增强方法类,并标注注解@Aspect表明这是一个切面容器,并使用Component注入容器,在该类中,使用@Pointcut注解标注切点

/**
 * 操作日志 AOP
 *
 * @author zqf
 */
@Aspect
@Component
public class OperateLogAspect {

    @Pointcut("@annotation(operateLog)")
    public void operateLogPoint(OperateLog operateLog) {
    }

    /**
     * 前置方法
     *
     * 在目标方法之前执行
     */
    @Before(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
    public void before(JoinPoint joinPoint, OperateLog operateLog) {
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();

        System.out.println("===== 执行前置方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("参数>>>" + Arrays.asList(args).toString());
    }

    /**
     * 后置方法
     *
     * 即使目标方法出错抛出异常也不影响执行
     */
    @After(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
    public void after(JoinPoint joinPoint, OperateLog operateLog) {
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();

        System.out.println("===== 执行后置方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("参数>>>" + Arrays.asList(args).toString());
    }

    /**
     * 环绕方法
     *
     * 只有调用 proceedingJoinPoint.proceed()方法才能够执行目标方法
     */
    @Around(value = "operateLogPoint(operateLog)", argNames = "proceedingJoinPoint,operateLog")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, OperateLog operateLog) throws Throwable {
        String methodName = proceedingJoinPoint.getTarget().getClass().getSimpleName() + "#" + proceedingJoinPoint.getSignature().getName();
        String operateType = operateLog.operateType().name();

        System.out.println("===== 执行环绕前方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("执行操作>>>" + operateType);

        // 目标方法的执行
        Object proceed = proceedingJoinPoint.proceed();

        System.out.println("===== 执行环绕后方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("执行操作>>>" + operateType);

        return proceed;
    }

    /**
     * AfterReturning 方法
     *
     * 当方法正常执行返回时才执行该方法,若抛出异常则不会执行该方法
     */
    @AfterReturning(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
    public void afterReturning(JoinPoint joinPoint, OperateLog operateLog) {
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();

        System.out.println("===== 执行 AfterReturning 方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("参数>>>" + Arrays.asList(args).toString());
    }

    /**
     * AfterThrowing 方法
     *
     * 当方法抛出异常时执行该方法,弱方法正常执行则不执行该方法
     */
    @AfterThrowing(value = "operateLogPoint(operateLog)", argNames = "joinPoint,operateLog")
    public void afterThrowing(JoinPoint joinPoint, OperateLog operateLog) {
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getTarget().getClass().getSimpleName() + "#" + joinPoint.getSignature().getName();

        System.out.println("===== 执行 AfterThrowing 方法 =====");
        System.out.println("方法名>>>" + methodName);
        System.out.println("参数>>>" + Arrays.asList(args).toString());
    }

}

编写控制类进行测试

/**
 * AOP 测试 Controller
 *
 * @author zqf
 */
@RestController
@RequestMapping("/aop")
public class AopController {

    @OperateLog(operateType = OperateTypeEnum.ADD)
    @PostMapping("/add")
    public String add() {
        System.out.println("=====执行调用方法add()=====");
        return "执行添加成功~";
    }

    @OperateLog(operateType = OperateTypeEnum.DELETE)
    @DeleteMapping("/delete")
    public String delete() {
        System.out.println("=====执行调用方法delete()=====");
        return "执行删除成功~";
    }

    @OperateLog(operateType = OperateTypeEnum.UPDATE)
    @PutMapping("/update")
    public String update() {
        System.out.println("=====执行调用方法update()=====");
        return "执行更新成功~";
    }

    @OperateLog(operateType = OperateTypeEnum.GET)
    @GetMapping("/get")
    public String get() {
        System.out.println("=====执行调用方法get()=====");
        // 测试 @AfterThrowing
        throw new RuntimeException("测试 @AfterThrowing");
    }

}

测试正常运行结果

【总结】SpringBoot AOP 搭配注解的使用_第1张图片
测试运行异常结果
【总结】SpringBoot AOP 搭配注解的使用_第2张图片

你可能感兴趣的:(SpringBoot,spring,boot,java,spring)