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

SpringBoot通过自定义注解实现日志打印

目录

前言:

正文

一.Spring AOP

1.JDK动态代理

2.Cglib动态代理

使用AOP主要的应用场景:

SpringBoot通过自定义注解实现日志打印

一.Maven依赖

二.ControllerMethodLog.class自定义注解

三.Spring AOP切面方法的执行顺序

四.ControllerMethodLogAspect.class:用于打印日志的切面定义类


前言:


在我们日常的开发过程中通过打印详细的日志信息能够帮助我们很好地去发现开发过程中可能出现的​​Bug​​​,特别是在开发​​Controller​​​层的接口时,我们一般会打印出​​Request​​​请求参数和​​Response​​响应结果,但是如果这些打印日志的代码相对而言还是比较重复的,那么我们可以通过什么样的方式来简化日志打印的代码呢?

正文


一.Spring AOP


Spring AOP 即面向切面,是对​​OOP​​​面向对象的一种延伸。
​​​AOP​​​机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码。在业务流程执行过程中,​​Spring​​框架会根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置。

Spring AOP的实现方式

1.JDK动态代理

  • 类对象必须实现接口
  • ​​JDK​​​动态代理,背后是借助​​Java​​​多态的特性,因为​​JDK​​​动态代理生成的​​class​​​文件已经继承了​​Proxy​​​,而​​Java​​​是单继承的,不能继承目标对象,只能实现目标对象(涉及向上转型),所以是基于​​JDK​​动态代理是基于接口的。

​​JDK​​动态代理主要涉及两个类:

  • ​​InvocationHandler​​是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。
  • ​​Proxy​​​ 利用 ​​InvocationHandler​​ 动态创建 一个符合某一接口的实例,生成目标类的代理对象。

2.Cglib动态代理

  • ​​Cglib​​​是一个强大的高性能,高质量的代码生成类库, 可以在运行期扩展 ​​Java​​​ 类与实现 ​​Java​​​ 接口,​​CgLib​​​ 封装了​​asm​​​,可以再运行期动态生成新 的 ​​class​​。

特别要注意的是:

  • 目标类实现接口的情况下使用​​JDK​​​动态代理,没有实现接口的情况下使用​​Cglib​​动态代理。
  • 可以使用​​ProxyTargetClass = true​​​,强制所有都使用​​Cglib​​动态代理。
  • ​​Cglib​​​所创建的动态代理对象在实际运行时候的性能要比​​JDK​​​动态代理高不少,有研究表明,大概要高10倍;但是​​Cglib​​​在创建对象的时候所花费的时间却比​​JDK​​动态代理要多很多,有研究表明,大概有8倍的差距;
  • 对于​​singleton​​​的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用​​Cglib​​​动态代理,反正,则比较适用​​JDK​​动态代理。

使用AOP主要的应用场景:

  • ​​Authentication​​ 权限检查
  • ​​Caching​​ 缓存
  • ​​Context passing​​ 内容传递
  • ​​Error handling​​ 错误处理
  • ​​Lazy loading​​ 延迟加载
  • ​​Debugging​​ 调试
  • ​​logging, tracing, profiling and monitoring​​日志记录,跟踪,优化,校准
  • ​​Performance optimization​​性能优化,效率检查
  • ​​Persistence​​ 持久化
  • ​​Resource pooling​​资源池
  • ​​Synchronization​​同步
  • ​​Transactions​​ 事务管理

SpringBoot通过自定义注解实现日志打印


一.Maven依赖

<!--lombok-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.2</version><optional>true</optional>
</dependency><!--Spring AOP-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>


二.ControllerMethodLog.class自定义注解

​​@Retention​​: 用来修饰注解,是注解的注解,称为元注解。
​​@Target​​:用来说明对象的作用范围
​​@Documented​​:用来做标记使用

/**
* 自定义注解用于打印Controller层方式日志
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ControllerMethodLog {
}



这里特别讲一下​​@Retention​​,按生命周期来划分可分为3类:

  • ​​RetentionPolicy.SOURCE​​​:注解只保留在源文件,当​​Java​​​文件编译成​​class​​文件的时候,注解被遗弃(运行时去动态获取注解信息);
  • ​​RetentionPolicy.CLASS​​​:注解被保留到​​class​​​文件,但​​jvm​​​加载​​class​​文件时候被遗弃,这是默认的生命周期(在编译时进行一些预处理操作);
  • ​​RetentionPolicy.RUNTIME​​​:注解不仅被保存到​​class​​​文件中,​​jvm​​​加载​​class​​文件之后,仍然存在(做一些检查性的操作);

这3个生命周期分别对应于:​​Java​​​源文件(​​.java​​​文件) —> ​​.class​​文件 —> 内存中的字节码。

三.Spring AOP切面方法的执行顺序


这里简单介绍一下,切面的执行方法和其执行顺序:

  • ​​@Around​​ 通知方法将目标方法封装起来
  • ​​@Before​​ 通知方法会在目标方法调用之前执行
  • ​​@After​​ 通知方法会在目标方法返回或者异常后执行
  • ​​@AfterReturning​​ 通知方法会在目标方法返回时执行
  • ​​@Afterthrowing​​ 通知方法会在目标方法抛出异常时执行

这里以一个返回正常的情况为例:(异常替换最后一步即可)

四.ControllerMethodLogAspect.class:用于打印日志的切面定义类

注意要在启动类扫描这个​​class​​​,并且添加 ​​@EnableAspectJAutoProxy(proxyTargetClass = true)​​

@Slf4j
@Component
@Aspect
public class ControllerMethodLogAspect {@Pointcut("@annotation(com.xiyuan.demo.annotation.ControllerMethodLog)")public void pointCut() {}/*** 在切点运行前执行该方法*/@Before("pointCut()")public void doBefore(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();ControllerMethodLog annotation = method.getAnnotation(ControllerMethodLog.class);if (Objects.isNull(annotation)) {return;}String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName();log.info("start {}:入参:{}", methodName, JSON.toJSONString(joinPoint.getArgs()));}/*** 在切点运行后,无异常时执行该方法** @param joinPoint* @param result*/@AfterReturning(value = "pointCut()", returning = "result")public void afterReturn(JoinPoint joinPoint, Object result) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();ControllerMethodLog annotation = method.getAnnotation(ControllerMethodLog.class);if (Objects.isNull(annotation)) {return;}String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName();log.info("end {}:响应:{}", methodName, JSON.toJSONString(result));}}


验证
getUserById:根据id获取用户的信息

@GetMapping("/getUserById")
@ApiOperation(value = "根据用户id获取用户")
@ControllerMethodLog
public ResponseResult getUserById(@RequestParam(name = "id", required = true) String id) {UserInfoPojo userInfoPojo = userService.getUserById(id);return ResponseResult.success(userInfoPojo, ConstantsUtil.QUERY_SUCCESS);
}


Swagger接口信息如下:

IDEA控制台打印信息如下:

相关文章:

SpringBoot通过自定义注解实现日志打印

目录 前言&#xff1a; 正文 一.Spring AOP 1.JDK动态代理 2.Cglib动态代理 使用AOP主要的应用场景&#xff1a; SpringBoot通过自定义注解实现日志打印 一.Maven依赖 二.ControllerMethodLog.class自定义注解 三.Spring AOP切面方法的执行顺序 四.ControllerMethodL…...

代码随想录算法训练营第七天 |151.翻转字符串里的单词

今天是代码随想录的第七天&#xff0c;写了力扣的151.翻转字符串里的单词&#xff1b; 之后或许还要再琢磨琢磨 代码随想录链接 力扣链接 151.翻转字符串里的单词&#xff0c;代码如下&#xff1a; # class Solution: # def reverseWords(self, s: str) -> str: # …...

【WebRTC---源码篇】(十:一)WEBRTC 发送视频RTP包

RTPSenderVideo在整个框架中起到重要的作用,它把采集的数据进行编码,并且在流程中会进行将编码后的数据进行RTP打包,最后发送到网络层 RTPSenderVideo::SendVideo //对编码数据打包 bool RTPSenderVideo::SendVideo(int payload_type,absl::optional<VideoCodecType>…...

cmd 90 validate error!(达梦数据库日志报错)

达梦数据库报错 error-cmd 90 validate error! 环境介绍1 解决办法 环境介绍 某生产环境数据库启动后&#xff0c;dm_实例名_202309.log&#xff0c;偶尔报错cmd 90 validate error! 1 解决办法 接口用错了&#xff0c;消息非法&#xff0c;比如用 6 的 JDBC 连 7 或 7 的 …...

Shape Completion Enabled Robotic Grasping

摘要-这项工作提供了一个架构&#xff0c;使机器人能够通过形状完成抓取规划。形状完成是通过使用3D卷积神经网络(CNN)来完成的。该网络是在我们自己的新的开源数据集上训练的&#xff0c;该数据集包含了从不同视角捕获的超过44万个3D样本。运行时&#xff0c;从单个视角捕获的…...

【C++】构造函数意义 ( 构造函数显式调用与隐式调用 | 构造函数替代方案 - 初始化函数 | 初始化函数缺陷 | 默认构造函数 )

文章目录 一、构造函数意义1、类的构造函数2、构造函数显式调用与隐式调用3、构造函数替代方案 - 初始化函数4、初始化函数缺陷5、默认构造函数6、代码示例 - 初始化函数无法及时调用 一、构造函数意义 1、类的构造函数 C 提供的 构造函数 和 析构函数 作为 类实例对象的 初始化…...

VMware16安装ghost版win7

文章目录 准备工作GHO 文件装机工具 新建虚拟机配置虚拟机还需要一个 CD/DVD PE 安装步骤分区还原挂载 CD/DVD开始还原 还原之后 准备工作 GHO 文件 可以去百度搜索这种文件&#xff0c;我这里是从系统之家下载的deepin win7 ghost 系统 装机工具 因为下载的 ghost 版的 w…...

项目集成swagger,访问不到swagger页面

项目集成swagger 文章目录 前言一、背景二、问题复现1.Full authentication is required to access this resource2.Illegal DefaultValue null for parameter type integer 总结 前言 项目集成swagger这个没啥好整的&#xff0c;maven项目就在pom文件导入依赖&#xff0c;ser…...

微信小程序怎么隐藏顶部导航栏(navigationBar)变透明的解决方案

怎么隐藏小程序顶部导航栏&#xff08;navigationBar&#xff09;&#xff1f; 官网说&#xff1a;Navigation是小程序的顶部导航组件&#xff0c;当页面配置 navigationStyle 设置为 custom 的时候可以使用此组件替代原生导航栏。 那么&#xff0c;我们就知道这种效果是可以…...

RabbitMQ基础概念-02

RabbitMQ是基于AMQP协议开发的一个MQ产品&#xff0c; 首先我们以Web管理页面为 入口&#xff0c;来了解下RabbitMQ的一些基础概念&#xff0c;这样我们后续才好针对这些基础概念 进行编程实战。 可以参照下图来理解RabbitMQ当中的基础概念&#xff1a; 虚拟主机 virtual hos…...

从构建者到设计者的低代码之路

低代码开发技术&#xff0c;是指无需编码或通过少量代码就可以快速生成应用程序的工具&#xff0c;一方面可降低企业应用开发人力成本和对专业软件人才的需求&#xff0c;另一方面可将原有数月甚至数年的开发时间成倍缩短&#xff0c;帮助企业实现降本增效、灵活迭代。那么&…...

Linux创建进程 及父子进程虚拟空间 多进程GDB调试

父子进程的资源是读时共享&#xff0c;写时拷贝&#xff0c;用到某一个资源&#xff0c;比如说改变变量的值的时候才去拷贝这个变量到一个独立的空间 父子进程的关系&#xff1a; 区别&#xff1a; 1.fork&#xff08;&#xff09;函数的返回值不同 父进程中&#xff1a;>…...

uni-app 之 表格设置

uni-app 之 表格设置 image.png <view style"padding: 3%; border: #1296db;"><table style"width: 100%; border-collapse: collapse; "><tr style"height: 50px;border: 2px solid;border-color: #F7F7F7;"><td style&qu…...

Linux易混淆知识点

1. 使用 vi 编辑某个文件时&#xff0c;执行删除某行/某几行的操作&#xff1a; dd&#xff1a;删除光标所在行&#xff1b; 6dd&#xff1a;表示删除当前行开始 6 行数据。 ndd&#xff1a; 删除当前行开始的连续 n 行&#xff1b; n1,n2d&#xff1a;删除 n1 到 n2 行&#x…...

移植FlashDB、SFUD到STM32f407

个人上篇文章 搭建STM32F407的SPI-Flash&#xff08;基于STM32CubeMX&#xff09;_小刚学長的博客-CSDN博客 主要是解决STM32CubeMX这边的配置&#xff0c;对code端侧是简单介绍了下 实际项目上一般都是拿片外flash存储一些东西&#xff0c;比如一些比较多的配置、参数&…...

【算法基础】时间复杂度和空间复杂度

目录 1 算法的评价 2 算法复杂度 2.1 时间复杂度&#xff08;Time Complexity&#xff09; 2.1.1 如何计算时间复杂度&#xff1a; 2.1.2 常见的时间复杂度类别与示例 2.2 空间复杂度 2.2.1 如何计算空间复杂度 2.2.2 常见的空间复杂度与示例 3 时间复杂度和空间复杂度…...

解决微信小程序不支持TextEncoder/TextDecoder对象

问题描述&#xff1a;在使用小程序开发者工具开发小程序中使用到了CRC算法&#xff0c;其中有一行代码使用到了TextEncoder对象&#xff0c;在开发工具中一切正常&#xff0c;到手机上会报出错误错误如下&#xff1a; MiniProgramError TextEncoder is not defined ReferenceEr…...

Qt下SVG格式图片应用

SVG格式图片介绍 svg格式图片又称矢量图&#xff0c;该种格式的图片不同于png等格式的图片&#xff0c;采用的并不是位图的形式来组织图片&#xff0c;而是采用线条等组织图片&#xff0c;svg格式是图片的文件格式是xml&#xff0c;可以通过文件编译器打开查看svg格式内容。 …...

python异常处理

参考语法&#xff1a;https://docs.python.org/zh-cn/3/tutorial/errors.html 在编写代码的时候&#xff0c;如果你写的程序出现报错&#xff0c;程序就会停止运行&#xff0c;后面的代码就不再执行。 如果程序发生错误&#xff0c;可以在代码中添加异常处理&#xff0c;保证程…...

go get命令不再具有安装功能

go get功能呢 一直以来&#xff0c;我们知道go get命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包&#xff0c;并自动完成编译和安装。整个过程就像安装一个App一样简单。 go get命令可以动态获取远程代码包&#xff0c;命令在内部实际上分成了两步操作&#x…...

QT界面开发:CCMusic音乐分类桌面应用制作

QT界面开发&#xff1a;CCMusic音乐分类桌面应用制作 1. 引言 你是否曾经想过自己动手制作一个能自动识别音乐风格的桌面应用&#xff1f;想象一下&#xff0c;只需点击几下&#xff0c;就能让电脑告诉你正在听的歌曲是摇滚、流行还是古典音乐。今天&#xff0c;我将带你用QT…...

SpringBoot+网关+配置中心动态降级联动避坑指南

在微服务架构落地过程中,SpringBoot+Spring Cloud Gateway+Nacos(配置中心)实现网关动态降级,是保障系统高可用的核心方案之一。但实际开发中,很多开发者会在三者联动时踩各种“隐形坑”,导致降级开关不生效、过滤器失灵、核心路由误降级等问题,既耽误开发进度,也可能引…...

NX二次开发C#-----NXopen测量两个面的投影距离

该代码实现了一个计算两个面之间投影距离的方法。通过创建工作部件中的测量距离构建器&#xff0c;设置投影方向为指定向量&#xff0c;并指定两个测量面对象。使用最小投影距离算法创建测量对象&#xff0c;最终返回两个面之间的投影距离值。计算完成后销毁测量构建器以释放资…...

SpringSecurity知识点

1、什么是Spring Security&#xff1f;核心功能&#xff1f;Spring Security是一个基于 Spring 框架的安全框架&#xff0c;提供了完整的安全解决方案&#xff0c;包括认证、授权、攻击防护等功能。其核心功能包括&#xff1a;认证&#xff1a;提供了多种认证方式&#xff0c;如…...

自我介绍

我叫代禄用&#xff0c;20岁&#xff0c;就读于重庆电子科技职业大学&#xff0c;本科&#xff0c;专业是物联网工程技术&#xff0c;刚刚开始学习c语言&#xff0c;肯定是为了以后更好就业&#xff0c;能从事这个方面的工作&#xff0c;我打算不仅跟着学校的课程&#xff0c;还…...

2026首版次高端软件申报全流程指南:中承信安权威解析

对于国内深耕自主研发的软件企业而言&#xff0c;自主研发的高端软件产品&#xff0c;不仅是企业核心竞争力的核心载体&#xff0c;更能通过首版次高端软件申报&#xff0c;获得真金白银的政策补贴、官方资质背书与市场竞争力的双重提升。但不少企业面临政策解读不到位、申报范…...

多线程Web代理服务器:Computer-Networking-A-Top-Down-Approach-NOTES作业4教程

多线程Web代理服务器&#xff1a;Computer-Networking-A-Top-Down-Approach-NOTES作业4教程 【免费下载链接】Computer-Networking-A-Top-Down-Approach-NOTES 《计算机网络&#xff0d;自顶向下方法(原书第6版)》编程作业&#xff0c;Wireshark实验文档的翻译和解答。 项目地…...

OCRmyPDF与区块链身份:使用OCR验证数字身份文档的完整指南

OCRmyPDF与区块链身份&#xff1a;使用OCR验证数字身份文档的完整指南 【免费下载链接】OCRmyPDF 项目地址: https://gitcode.com/gh_mirrors/ocr/OCRmyPDF OCRmyPDF是一款强大的开源工具&#xff0c;能够将扫描的PDF文档转换为可搜索、可复制的文本&#xff0c;这一核…...

深入解析ConvLoRA:如何通过卷积增强LoRA在SAM模型中的微调效率

1. 为什么SAM模型微调需要ConvLoRA&#xff1f; 如果你玩过Meta开源的Segment Anything Model&#xff08;SAM&#xff09;&#xff0c;大概率会有这样的体验&#xff1a;这个模型在“分割一切”的通用能力上确实惊艳&#xff0c;但当你把它拿到自己的具体任务上&#xff0c;比…...

Dataset - DeepFashion:从数据构建到时尚AI应用实战

1. 从零开始&#xff1a;认识DeepFashion&#xff0c;你的时尚AI“弹药库” 如果你对用AI做点跟时尚相关的事情感兴趣&#xff0c;比如让机器自动识别一件衣服是“圆领T恤”还是“高腰阔腿裤”&#xff0c;或者想做一个能根据用户上传的图片推荐相似款式的购物助手&#xff0c;…...