AOP:面向切面编程,在不改变原有方法的基础上增强原有方法。
代码实现
1.自定义日志注解注解
1.1添加元注解(基础注解)@Target、@Retention、@Documented
元注解的作用就是负责注解其他注解
@Target:用于描述注解的使用范围,该注解可以使用在什么地方
@Retention:表明该注解的生命周期
@Documented:表明该注解标记的元素可以被Javadoc 或类似的工具文档化
1.2添加两个自定义参数
module 模块
operator 操作名称
@Target(ElementType.METHOD) // 这里的METHOD代表该自定义注解可以放在方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
//自定义两个参数(默认值为空),使用此注解的时候就可以携带参数
String module() default "";
String operator() default "";
}
2.AOP切面
切面定义了通知和切点的关系
简单的理解使用 @Aspect 注解的类就是切面
切入点:使用@Pointcut()注解标识我们的切点,并且指向我们自定义的注解
通知:在通知类上面使用@Around()标识切点,通过切点就能执行我们的通知类。
通过反射机制,拿到注解的方法,可以知道模块名和具体操作
通过传递的参数ProceedingJoinPoint(连接点)得到请求的相关信息
最后利用@Slf4j 打印日志。
@Aspect
@Component //添加为组件
@Slf4j //日志
public class LogAspect {
/**
* 切点
*/
@Pointcut("@annotation(com.example.myblog.common.aop.LogAnnotation)")
public void logPointCut() {
}
/**
* 通知类
* 环绕通知 能对我们的方法前后都进行增强
* @param point
* @return
* @throws Throwable
*/
@Around("logPointCut()") //标识切点
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法 调用我们原有的方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
recordLog(point, time);
return result;
}
private void recordLog(ProceedingJoinPoint joinPoint, long time) {
//通过反射的形式拿到我们的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
log.info("=====================log start================================");
log.info("module:{}",logAnnotation.module()); //模块名
log.info("operation:{}",logAnnotation.operator()); //具体操作
//请求的方法名
String className = joinPoint.getTarget().getClass().getName(); //请求的接口名称
String methodName = signature.getName(); //请求的方法名称
log.info("request method:{}",className + "." + methodName + "()");
// //请求的参数
Object[] args = joinPoint.getArgs();
String params = JSON.toJSONString(args[0]); //转化成JSON格式
log.info("params:{}",params);
log.info("excute time : {} ms",time);
log.info("=====================log end================================");
}
}
3.使用(在方法上使用)
@PostMapping()
//加上此注解代表要对此接口记录日志
@LogAnnotation(module="文章", operator="获取文章列表") //(模块名称,操作参数)
public Result articles(@RequestBody PageParams pageParams) {
//ArticleVo 页面接收的数据
List<ArticleVO> articles = articleService.listArticlesPage(pageParams);
return Result.success(articles);
}
4.结果
image.png参考文章: 这里
网友评论