java自定义注解

本文介绍了如何在Spring框架中使用AspectJ创建切点和切面,通过自定义注解`ParemLog`实现方法执行前后及异常时的操作日志记录。
摘要由CSDN通过智能技术生成

第一步:创建切点

package cn.iocoder.yudao.module.system.util.note;

import java.lang.annotation.*;

/**
 * @Describe
 * @Package cn.iocoder.yudao.framework.common.note
 * @Date 2024/1/19 10:06
 */
@Target({ ElementType.TYPE, ElementType.METHOD })//声明作用范围
@Retention(RetentionPolicy.RUNTIME) //注解生命周期
public @interface ParemLog {
 	String name() default "";
    String value() default "";
}

@Target声明注解的作用范围,超过这个范围会报错。
以下是@Target:注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包,用于记录java文件的package信息

第二步:创建切面

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Describe
 * @Package cn.iocoder.yudao.framework.common.note
 * @Date 2024/1/19 10:11
 */
@Aspect //声明为切面
@Component
@Slf4j
public class ParemLogAspect {

/**
     * 定义一个切点,用于匹配需要拦截的方法
     */
    @Pointcut(value = "@annotation(cn.iocoder.yudao.module.system.util.note.ParemLog)")
    public void ParemLog() {

    }

    /**
     * 前置操作--在方法执行之前执行
     * @param joinPoint
     */
    @Before(value = "@annotation(cn.iocoder.yudao.module.system.util.note.ParemLog)")
    public void Before(JoinPoint joinPoint) {
        log.info("===========前置操作===========");
        System.out.println("getTarget:"+joinPoint.getTarget().getClass().getName()); //类路径
        for (Object arg : joinPoint.getArgs()) {
            System.out.println("参数:"+arg); //   获取参数
        }
        System.out.println("getSignature"+joinPoint.getSignature().getName()); //获取方法名
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operation = "";
            String operations = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class<?>[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        operation = method.getAnnotation(ParemLog.class).value();//获取自定义注解参数
                        operations = method.getAnnotation(ParemLog.class).name();//获取自定义注解参数
                        break;
                    }
                }
            }
            StringBuilder paramsBuf = new StringBuilder();
            for (Object arg : arguments) {
                paramsBuf.append(arg);
                paramsBuf.append("&");
            }
            // *========控制台输出=========*//
            log.info("[X用户]执行了[" + operation + operations +"],类:" + targetName + ",方法名:" + methodName + ",参数:"
                    + paramsBuf.toString());
            log.info("=====================执行后置通知结束==================");
        } catch (Throwable e) {
            log.info("around " + joinPoint + " with exception : " + e.getMessage());
        }
    }

    /**
     * 后置操作 方法执行后执行
     * @param joinPoint
     *
     **/
   @After(value = "@annotation(cn.iocoder.yudao.module.system.util.note.ParemLog)")
   public void After(JoinPoint joinPoint) {
        log.info("=====================执行后置通知结束==================");
   }


    /**
     * 后置操作--在方法正常执行之后执行
     * @param
     */
 @AfterReturning(pointcut = "ParemLog()",returning = "ret")
    public void AfterReturning(JoinPoint joinPoint, Object ret){
        log.info("===========后置操作--方法无异常时执行===========");
        log.info("返回值信息:"+ret);
    }

    /**
     * 后置操作--方法异常执行
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "@annotation(cn.iocoder.yudao.module.system.util.note.ParemLog)", throwing = "e")
    public void AfterThrowing(JoinPoint joinPoint, Throwable e){
        log.info("===========后置操作--方法异常执行===========");
        log.info("异常信息:"+e); //打印异常信息
    }

}

JoinPoint 介绍

常用方法如下:
1、获取方法调用时,传入的参数

Object[] args = joinPoint.getArgs();

2、获取代理方法的信息

MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取代理方法的信息
String methodName = signature.getName(); // 获取方法名
Class<?> returnType = signature.getReturnType(); // 获取返回类型
Class<?>[] parameterTypes = signature.getParameterTypes(); // 获取参数类型数组

在这个示例中,我们首先使用joinPoint.getSignature() 方法获取代理方法的信息,然后将其转换为MethodSignature类型的对象。接着我们可以通过MethodSignature对象的方法获取方法名、返回类型、参数类型等信息,用于在通知中进行处理

3、获取目标对象

Object target = joinPoint.getTarget();

总的来说,Joinpoint代表了AOP中能够被拦截的程序执行点,通过拦截来实现切点我们想实现的功能。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值