第一步:创建切点
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中能够被拦截的程序执行点,通过拦截来实现切点我们想实现的功能。