基于 Spring AOP (面向切面编程) 的切面类--自定义方法注解的方式打印日志

news/2024/11/28 0:21:30/

java___0">java每日一学 ---- 面向切面编程

怎么通过方法注解的方式打印日志呢?自定义注解

1、首先定义一个@ExecuteLog 注解类

java">@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExecuteLog {/*** 执行方法的描述,默认方法名** @return 描述*/String value() default "";boolean includeRequest() default true;boolean includeResult() default true;
}

方法讲解:
(1)、@Target(ElementType.METHOD)

作用:指定该注解只能应用于方法上。 解释:@Target 注解表示自定义注解的作用范围。这里的 ElementType.METHOD
表示该注解只能应用于方法。

(2)、@Retention(RetentionPolicy.RUNTIME)

作用:指定注解的生命周期。 解释:@Retention 注解表示注解的存活时间。RUNTIME 表示注解在运行时有效,可以通过反射机制访问。

(3)、String value() default “”;

作用:定义一个字符串属性 value,默认为空字符串。 解释:这个属性用于给方法添加一个描述信息,默认情况下,value
为方法名。如果方法没有显式提供描述,value 默认将是方法的名字。

(4)、boolean includeRequest() default true;

作用:定义一个布尔属性 includeRequest,默认为 true。 解释:决定在日志中是否包括请求参数。如果为
true,会记录请求参数;如果为 false,则不记录请求参数。

(5)、boolean includeResult() default true;

作用:定义一个布尔属性 includeResult,默认为 true。 解释:决定在日志中是否包括方法执行结果。如果为
true,会记录方法的返回值;如果为 false,则不记录方法的返回值。

2、ExecuteLogAspect 切面类,再定义一个切面类

java">@Aspect
@Component
public class ExecuteLogAspect {private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteLogAspect.class);@Around("@annotation(executeLog)")public Object recordIntervalLog(ProceedingJoinPoint pjp, ExecuteLog executeLog) throws Throwable {LocalDateTime beginTime = LocalDateTime.now();MethodSignature signature = (MethodSignature) pjp.getSignature();Object[] args = pjp.getArgs();Method method = signature.getMethod();String methodName = StringUtils.defaultIfBlank(executeLog.value(), method.getName());String processId = RandomUtils.getShortUUID();if (executeLog.includeRequest()) {LOGGER.info("start to process [{}], clientId [{}], userId [{}], params: [{}], startTime: [{}], processId: [{}]", methodName, AppContext.getClientId(), AppContext.getFineUid(), args, beginTime, processId);} else {LOGGER.info("start to process [{}], clientId [{}], userId [{}], startTime: [{}], processId: [{}]", methodName, AppContext.getClientId(), AppContext.getFineUid(), beginTime, processId);}Object result = pjp.proceed();LocalDateTime endTime = LocalDateTime.now();if (executeLog.includeResult()) {LOGGER.info("process[{}],Id: [{}] finished, result:[{}], endTime: [{}], costTime: [{}] ms", methodName, processId, result, endTime, beginTime.until(endTime, ChronoUnit.MILLIS));} else {LOGGER.info("process[{}],Id: [{}] finished, endTime: [{}], costTime: [{}] ms", methodName, processId, endTime, beginTime.until(endTime, ChronoUnit.MILLIS));}return result;}
}

(1)、@Aspect

作用:表示该类是一个切面类(Aspect)。 解释:@Aspect 是 AOP
编程中的关键注解,标记这个类为切面类,意味着这个类将包含切面逻辑,即方法执行前后做一些操作。

(2)、@Component

作用:表示该类是一个 Spring Bean。 解释:@Component 注解将这个类注册到 Spring 上下文中,Spring
容器会自动扫描并创建该类的实例,供其他组件使用。

(3)、@Around(“@annotation(executeLog)”)

作用:这是一个环绕通知,用来定义一个环绕方法。 解释:@Around 注解指定了一个切点,该切点是所有标注了 @ExecuteLog
注解的方法。通过 @annotation(executeLog),Spring 会将方法上注解的实例传递给方法参数 executeLog。

(4)、public Object recordIntervalLog(ProceedingJoinPoint pjp, ExecuteLog
executeLog) throws Throwable

作用:定义一个环绕通知方法。 解释:ProceedingJoinPoint
提供了对目标方法的控制,允许我们在方法执行前后做一些操作。ExecuteLog executeLog
用来接收目标方法上注解的实例,throws Throwable 表示该方法可能会抛出异常。

java">        LocalDateTime beginTime = LocalDateTime.now();MethodSignature signature = (MethodSignature) pjp.getSignature();Object[] args = pjp.getArgs();Method method = signature.getMethod();String methodName = StringUtils.defaultIfBlank(executeLog.value(), method.getName());String processId = RandomUtils.getShortUUID();

(5)、MethodSignature signature = (MethodSignature) pjp.getSignature();

作用:获取方法的签名信息。 解释:pjp.getSignature() 返回的是 MethodSignature
类型的对象,包含了方法的签名信息,MethodSignature 是 Signature 类的子类,提供了获取方法、参数类型等信息的方法。

(6)、Object[] args = pjp.getArgs();

作用:获取方法参数。 解释:pjp.getArgs() 获取目标方法的参数列表,供后续在日志中记录请求参数时使用。

(7)、Method method = signature.getMethod();

作用:获取目标方法的 Method 对象。 解释:signature.getMethod() 返回当前方法的 Method
对象,用来获取方法的详细信息。

(8)、String methodName = StringUtils.defaultIfBlank(executeLog.value(), method.getName());

作用:获取方法的名称,如果注解中 value 属性有设置,则使用该属性值,否则使用方法名。
解释:StringUtils.defaultIfBlank 会检查 executeLog.value()
是否为空或空白,如果是,则使用方法的名称 method.getName()。

(9)、Object result = pjp.proceed();

作用:执行目标方法。 解释:pjp.proceed() 调用目标方法并返回其结果。这里的 proceed() 是
ProceedingJoinPoint 提供的执行方法的 API。

3、 如何使用呢?

java"> @ExecuteLogfun getXXX(event: StreamStatusChangeEvent) {....}

结果:

打印日志:start to process [setExtractPendingAfterStreamFinished], clientId
[null], userId [null], params:
[[StreamStatusChangeEvent(connectId=xxx, taskId=xx, pluginId=xxx,
tableId=xx, status=Complete, task=ConnectionTaskDO(id=xx,
fineUid=null, pluginId=11024, connectId=xx, config=null, state=null,
configuredCatalog=null, streamNames=null, attempts=null,
syncRecordStat=null, status=null, startedAt=null, syncEndAt=null,
finishedAt=null, fullSync=null, errorMsg=null, createdAt=null,
updatedAt=Fri Nov 22 10:00:24 CST 2024, deletedAt=null, groupId=null,
extractTasks=null))]], startTime: [2024-11-22T10:03:16.101050],
processId: [b1edd217]


http://www.ppmy.cn/news/1550471.html

相关文章

计算机网络 第4章 网络层

计算机网络 (第八版)谢希仁 第 4 章 网络层4.2.2 IP地址**无分类编址CIDR**IP地址的特点 4.2.3 IP地址与MAC地址4.2.4 ARP 地址解析协议4.2.5 IP数据报的格式题目2:IP数据报分片与重组题目:计算IP数据报的首部校验和(不正确未改) …

SQL for XML

关系数据模型与SQL SQL for XML 模式名功能RAW返回的行作为元素,列值作为元素的属性AUTO返回表名对应节点名称的元素,每列的属性作为元素的属性输出输出,可形成简单嵌套结构EXPLICIT通过SELECT语法定义输出XML结构PATH列名或列别名作为XPAT…

C++中虚继承为什么可以解决菱形继承的数据冗余问题

在C中菱形继承会有数据冗余的问题发生,我们可以使用虚继承来解决,那虚继承的原理是什么,为什么它可以解决这个问题。 菱形继承的数据冗余问题 class A { public:int data; };class B : public A {};class C : public A {};class D : public…

eduSRC挖洞思路

声明 学习视频来自 B 站UP主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 ✍🏻作者简介:致…

重写get方法导致json序列化之后值改变的问题

重写get方法导致json序列化之后值改变的问题 问题描述 在开发中,我发现有一个接口某一个字段返回的值和数据库中的实际值并不一样 数据库中值: id diameter 1 10接口返回值: {"id": 1,"diameter": 5 }问题排查 发现,在getDiame…

10 —— Webpack打包模式

开发模式:development ;场景:本地开发 生产模式:production ; 场景:打包上线 这两种模式如何设置给webpack: 方式1.webpack.config.js 配置文件设置mode选项 module.exports { mode:produc…

tsx中使用el-dialog设置visible.sync,解决弹窗右上角叉号失效问题

在 TSX 中使用 el-dialog 设置 visible.sync 在 Vue 2 中,.sync 修饰符用于在父子组件之间同步属性值。然而,在 TSX 中并没有类似的 .sync 修饰符。如果要在 TSX 中实现类似的功能,需要手动实现。具体来说,可以通过监听 update:v…

Jackson 对象与json数据互转工具类JacksonUtil

下面是一个基于 Jackson 的工具类 JacksonUtil,用于在 Java 项目中实现对象与 JSON 数据之间的互相转换。该工具类具有简洁、易用、通用的特点。 package com.fy.common.util;import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core…