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

news2024/9/21 11:10:36

目录

前言:

正文

一.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控制台打印信息如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/988286.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WireShark抓包工具的安装

1.下载安装包 在官网或者电脑应用商城都可以下载 2.安装 打开安装包&#xff0c;点击next 点击next 选择UI界面&#xff0c;两种都装上 根据习惯选择 选择安装位置点击安装 开始安装安装成功

测试用例基础

测试用例概要 测试用例要素 测试环境,操作步骤,测试数据,预期结果 测试用例好处 提高测试效率,节省测试时间 测试用例是自动化测试用例的前提 测试用例设计方法 1.基于需求的设计方法 需求文档 --> 梳理需求(掌握需求) --> 针对文档设计测试用例(基于需求设计测…

无脑013—— win11配置mmdetection实现训练自己的vol格式(xml)数据集

昨天使用cascade——rcnn 实现了MSAR 1.0的训练&#xff0c;今天来回顾一下 参考资料&#xff1a; http://t.csdn.cn/8A5WE http://t.csdn.cn/ccOZg 电脑 笔记本电脑&#xff0c;拯救者Y7000P 2018款&#xff0c;GTX1060显卡6G显存 &#xff0c;cmd输入代码nvcc-version显示的C…

[docker]笔记-portainer的安装

1、portainer是一款可视化的容器管理软件&#xff0c;利用portainer可以轻松方便的管理和创建容器。portainer本身是一个容器&#xff0c;完全免费并且具有汉化版。本文介绍portainer的安装和使用。 2、安装好容器并配置好容器环境&#xff0c;可参照https://blog.csdn.net/bl…

redis实战篇之导入黑马点评项目

1. 搭建黑马点评项目 链接&#xff1a;https://pan.baidu.com/s/1Q0AAlb4jM-5Fc0H_RYUX-A?pwd6666 提取码&#xff1a;6666 1.1 首先&#xff0c;导入SQL文件 其中的表有&#xff1a; tb_user&#xff1a;用户表 tb_user_info&#xff1a;用户详情表 tb_shop&#xff1a;商户…

使用Vagrant创建和管理本地Kubernetes(K8s)集群的步骤是什么

文章目录 步骤1&#xff1a;准备环境步骤2&#xff1a;创建Vagrantfile步骤3&#xff1a;启动虚拟机步骤4&#xff1a;安装Kubernetes步骤5&#xff1a;配置Kubernetes网络插件步骤6&#xff1a;将Worker节点加入集群步骤7&#xff1a;验证集群步骤8&#xff1a;部署应用步骤9&…

部署笔记:文件句柄调整和磁盘分区 02

系统默认是1024&#xff0c;基本不够&#xff0c;会报“too many open files”的错误。因此需要调整。 系统文件句柄数调整 # 编辑打开文件&#xff0c;在文末追加两行配置 vim /etc/security/limits.conf # 需要添加的配置&#xff0c;注意别漏了前面的*号 # * 指所有用户、…

gitlab 合并分支

打开我们的gitlab&#xff0c;找到我们的项目&#xff0c;在左侧菜单中找到Merge requests&#xff0c;点击Merge requests&#xff0c;进入下一个页面 点击New merge requests&#xff0c;创建一个新的merge&#xff0c;进入下一个页面 选择自己分支和目标分支&#xff0c;自己…

如何在Windows中使用C#填写和提取PDF表单

如何在Windows中使用C#填写和提取PDF表单 PDF表单不仅允许用户填写和提交数据&#xff0c;也允许用户创建各种表单域收集用户的数据&#xff0c;并通过提取表单字段值&#xff0c;将收集和合并提交的数据进一步分析或处理。PDF通过电子方式填写、保存和共享的形式&#xff0c;…

WebDAV之π-Disk派盘 + 百灵创作

百灵创作是一款简约而不简单、功能强大且安全的高颜值码字工具,为网络写手和小说作者提供跨平台的写作环境,并提供强大的数据备份和云同步技术,以保障作者的数据安全,并提供流畅的多端无缝切换体验。 百灵创作的特点和功能包括: 简约而不简单:提供简洁直观的界面和操作,…

成都瀚网科技有限公司:抖音怎么绑定抖音小店才好?

抖音是一款非常流行的短视频应用&#xff0c;为用户提供了一个展示才华、分享生活的平台。在抖音上&#xff0c;用户可以通过绑定抖音商店来销售自己的产品或服务&#xff0c;从而实现商业变现。那么&#xff0c;抖音如何绑定抖音商店呢&#xff1f; 1、抖音如何绑定抖音商店&a…

注解方式配置SpringMVC

注解配置SpringMVC 1. 初始化类&#xff0c;代替web.xml2. 创建SpringConfig配置类&#xff0c;代替spring的配置文件3. 创建SpringMVCConfig配置类&#xff0c;代替SpringMVC.xml配置文件4. 项目结构 1. 初始化类&#xff0c;代替web.xml Spring3.2引入了一个便利的WebApplic…

解放程序员生产力的AI代码助手重磅来袭

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

生信教程:多序列比对

摘要 所有系统发育推断方法都需要同源数据集作为输入。因此&#xff0c;当核苷酸序列用于系统发育分析时&#xff0c;第一步通常是推断不同类群序列中的哪些核苷酸彼此同源&#xff0c;以便这些核苷酸之间的差异仅源于序列进化中发生的变化。不同序列的核苷酸之间的同源性推断最…

Windows11 上使用 QEMU 创建 Ubuntu aarch64(ARM64)虚拟机

文章目录 背景步骤要点一、下载QEMU二、下载 QEMU UEFI 固件文件三、Ubuntu 光盘镜像文件四、安装设置 QEMU五、创建虚拟网卡1、安装 tap-windows2、重命名新网卡3、共享物理网卡的网络 六、创建硬盘镜像七、从iso镜像安装虚拟机八、启动镜像九、连接 ssh过程中 powershell 执行…

【已更新建模代码】2023数学建模国赛B题matlab代码--多波束测线问题

一、 问题重述 1.1问题背景 海洋测深是测定水体深度与海底地形的重要任务&#xff0c;有两种主要技术&#xff1a;单波束测 深与多波束测深。单波束适用于简单任务&#xff0c;但多波束可提供更精确的地形数据。多 波束系统的关键在于覆盖宽度与重叠率的设计&#xff0c;以确保…

【Python 自动化】小说推文一键生成思路概述

最近看了一下小说推文成品软件的思路&#xff0c;发现可以完全迁移到我的 BookerAutoVideo 上面来。这篇短文里面&#xff0c;我试着分析一下整个推文视频生成的流程&#xff0c;以及简要阐述一下有什么工具。 整体流程是这样&#xff1a; 分句 原文是按照段落组织的&#xf…

下载安装包,安装 PySide2 到 windows 系统

20201206 修订&#xff1a;修改 PyCharm 中工具的配置描述 一、下载两个.whl 文件到本地&#xff0c; 可以在此下载 https://mirrors.tuna.tsinghua.edu.cn/ 我选用的是以下两个版本&#xff1a; shiboken2-5.15.2-5.15.2-cp35.cp36.cp37.cp38.cp39-none-win_amd64.whl …

Netty源码剖析之HashedWheelTimer时间轮

版本信息&#xff1a; JDK1.8 Netty-all:4.1.38.Final 时间轮的介绍 我们知道钟表分为很多块&#xff0c;每时钟滴答一次就往前走一个块&#xff0c;而时间轮就是使用这个思想。如下图 上图总共分为8块&#xff0c;每过100ms就往前走一块&#xff0c;然后周而复始。此时&#…

关于faust勒索病毒,这些您该了解,勒索病毒解密,数据恢复

faust勒索病毒是一种近年来流行的恶意软件&#xff0c;它通过对计算机系统进行加密并要求支付赎金来达到释放系统的目的。faust勒索病毒的流行程度和危害性不断上升&#xff0c;给企业和个人带来了严重的安全威胁。接下来云天数据恢复中心将从faust勒索病毒的背景、特点、危害、…