当前位置: 首页 > news >正文

10.若依的自定义注解 Log

若依框架的自定义注解Log的含义是记录调用该api请求的请求参数、请求体、响应时间等信息

自定义注解的四个步骤:

1)开启Aop EnableAspectJAutoProxy

在这里插入图片描述

默认同一个类下的方法调用不会走代理,exposeProxy = true 的含义是让AopContext上下文能够获取该代理。
上面这句话太过于抽象,这里举个例子就明确了

若依获取部门列表的方法,可以看出有个范围限制的注解
在这里插入图片描述
获取部门树结构,这里看出这里通过AopContext上下文获取代理,保证调用selectDeptList时DataScope注解生效,也就是只能查看自己权限范围内的部门树。
在这里插入图片描述

2. 定义注解

Target:指定注解可以用在方法上,也可以用在函数调用的参数上,还有Type、Field等。

Retention:包括三种,RetentionPolicy.SOURCE、RetentionPolicy.CLASS、RetentionPolicy.RUNTIME

Documented:javadoc文档
接口方法表示可设置参数
在这里插入图片描述

Target分类

TYPE

适用目标:类、接口(包括注解类型)、枚举

示例:@Controller, @Service

@Target(ElementType.TYPE)
public @interface Service {}@Service
public class UserService {}
FIELD

适用目标:字段(包括枚举常量)

示例:@Autowired, @Value

@Target(ElementType.FIELD)
public @interface MaxLength {int value() default 100;
}public class User {@MaxLength(50)private String username;
}
METHOD

适用目标:方法

示例:@Override, @RequestMapping

@Target(ElementType.METHOD)
public @interface LogExecutionTime {}public class OrderService {@LogExecutionTimepublic void placeOrder() {}
}
PARAMETER

适用目标:方法参数

示例:@RequestParam, @PathVariable

@Target(ElementType.PARAMETER)
public @interface NotNull {}public class ValidationService {public void validateUser(@NotNull String username) {}
}
CONSTRUCTOR

适用目标:构造方法

示例:@Autowired (用于构造方法)

@Target(ElementType.CONSTRUCTOR)
public @interface Inject {}public class PaymentService {@Injectpublic PaymentService() {}
}
LOCAL_VARIABLE

适用目标:局部变量

注意:很少用于自定义注解,通常用于静态分析工具

@Target(ElementType.LOCAL_VARIABLE)
public @interface SuppressWarning {}public class Example {public void demo() {@SuppressWarningString temp = "test";}
}
ANNOTATION_TYPE

适用目标:注解类型(用于元注解)

示例:@Target, @Retention 本身

ANNOTATION_TYPE 是 ElementType
中的一个特殊值,它表示注解可以用在其他注解上(即修饰注解的注解,称为元注解)。这种机制主要用于定义注解的元数据,例如控制注解的生命周期(@Retention)、作用目标(@Target)等。

PACKAGE

适用目标:包

示例:@Package-info 中的注解

@Target(ElementType.PACKAGE)
public @interface PackageInfo {}@PackageInfo
package com.example;
TYPE_PARAMETER (Java 8+)

适用目标:类型参数(泛型参数)

示例:class MyClass<@MyAnnotation T>

@Target(ElementType.TYPE_PARAMETER)
public @interface NonNull {}public class Box<@NonNull T> {}
TYPE_USE (Java 8+)

适用目标:类型使用的任何地方

包括:类型声明、类型参数、throws子句等

@Target(ElementType.TYPE_USE)
public @interface NonNull {}public class Example {private List<@NonNull String> names;public @NonNull String getName() { return ""; }
}

Retention分类

RetentionPolicy.SOURCE

源码使用,不会被编译到class,典型应用Override
在这里插入图片描述

RetentionPolicy.CLASS

保留到编译后的 .class 文件中,不会被加载到JVM中,运行时无法通过反射获取,主要在类加载时或编译后处理阶段被工具处理。
也就是通过字节码可以看到该定义,一般用于静态工具使用。

RetentionPolicy.RUNTIME

我们一般定义的都是该类型,在运行过程中反射API,获取注解信息

3. 注解实现

ElementType.METHOD 切面位置

@Around

环绕通知,在目标方法执行前后都执行,可以控制方法是否执行。

@Before

前置通知,在目标方法执行前执行。

@After

后置通知,在目标方法执行后执行(无论是否抛出异常)。

@AfterReturning

返回通知,在目标方法正常返回后执行。

@AfterThrowing

异常通知,在目标方法抛出异常后执行。

@Pointcut
定义切点表达式,通常不直接标注在方法上,但可以引用方法作为切点。
举例:

// 定义切点:匹配 com.example.service 包下的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}// 环绕通知:记录方法执行时间
@Around("serviceLayer()")  // 引用切点
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = joinPoint.proceed(); // 执行目标方法long duration = System.currentTimeMillis() - startTime;System.out.println(joinPoint.getSignature() + " executed in " + duration + "ms");return result;
}

下面来看下Log实现了哪些方法:

  1. 当前线程记录调用方法开始的时间
@Before(value = "@annotation(controllerLog)")
public void doBefore(JoinPoint joinPoint, Log controllerLog)
{TIME_THREADLOCAL.set(System.currentTimeMillis());
}
  1. 正常返回,没有抛异常执行
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult){handleLog(joinPoint, controllerLog, null, jsonResult);}

pointcut表示要匹配哪些注解,"@annotation(controllerLog)"表示匹配所有带有@controllerLog注解的方法
returning = "jsonResult"表示将返回值绑定到通知方法的jsonResult参数上

handleLog 的实现比较简单,获取当前用户、IP、请求参数等,将其记录到数据中。下面几个函数用法可以学习下

//通过joinPoint获取注解调用方法的所在类名、方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();

4. 应用注解

应用注解,会在操作记录表中插入一行数据
在这里插入图片描述

http://www.dtcms.com/a/302013.html

相关文章:

  • 发布“悟能”具身智能平台,商汤让机器人像人一样和现实世界交互
  • GitLab 18.2 发布几十项与 DevSecOps 有关的功能,可升级体验【一】
  • RAGFlow系列(03):把知识库通过API方式共享给Dify等外部平台使用
  • WPS 将一个PPT里面的图片和文字导入到另一个PPT中
  • CSP-J 2022_第三题逻辑表达式
  • 面试官:详细说说Kafka rebalance 的策略以及具体过程
  • 中国计算机学会(CCF)推荐学术会议-B(数据库/数据挖掘/内容检索):WSDM 2026
  • Rust并发编程中的所有权挑战与解决方案:从实际项目看Clone策略的应用
  • vue3卡片垂直无限滚动
  • Android 中 TCP 协议的实战运用
  • 【JAVA安全-Fastjson系列】Fastjson 1.2.24 反序列化漏洞分析及测试环境构建【复习回顾】
  • 安宝特案例丨户外通信机房施工革新:AR+作业流技术破解行业难题
  • 安宝特案例丨AR+AI赋能轨道交通制造:破解人工装配难题的创新实践
  • AR技术赋能工业设备维护:效率与智能的飞跃
  • keeplived实例
  • 基于Verilog的神经网络加速器设计
  • 微信小程序点击输入框时,顶部导航栏被遮挡问题如何解决?
  • 数值计算 | 图解基于龙格库塔法的微分方程计算与连续系统离散化(附Python实现)
  • 软件测试开发转型经验分享与职业发展指南
  • 基于FPGA和DDS原理的任意波形发生器(含仿真)
  • 可配置的PWM外设模块
  • Java Collections工具类
  • RocketMQ入门实战详解
  • 【MySQL学习|黑马笔记|Day1】数据库概述,SQL|通用语法、SQL分类、DDL
  • 【数据标注】详解使用 Labelimg 进行数据标注的 Conda 环境搭建与操作流程
  • 【unitrix】 6.20 非零整数特质(non_zero.rs)
  • 做了一款小而美的本地校验器
  • 【保姆级喂饭教程】Python依赖管理工具大全:Virtualenv、venv、Pipenv、Poetry、pdm、Rye、UV、Conda、Pixi等
  • 【el-table滚动事件】el-table表格滚动时,获取可视窗口内的行数据
  • 电磁兼容五:仿真技术