高级开发!性能优化,Spring Boot 不使用AOP也能优雅的记录日志

文摘   2025-01-22 08:00   新疆  

Spring Boot 3实战案例合集》现已囊括超过80篇精选实战文章,并且此合集承诺将永久持续更新,为您带来最前沿的技术资讯与实践经验。欢迎积极订阅,享受不断升级的知识盛宴!订阅用户将特别获赠合集内所有文章的最终版MD文档(详尽学习笔记),以及完整的项目源码,助您在学习道路上畅通无阻。

【重磅发布】《Spring Boot 3实战案例锦集》PDF电子书现已出炉!

🎉🎉我们精心打造的《Spring Boot 3实战案例锦集》PDF电子书现已正式完成,目前已经有80个案例,后续还将继续更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。这意味着,随着技术的不断发展和Spring Boot 3的深入应用,我们的电子书也将持续更新,确保您始终掌握最前沿、最实用的技术知识。

💌💌如何获取
请立即订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

现在就订阅合集




环境:SpringBoot3.2.5



1. 简介

在项目开发中,日志记录是监控、调试和故障排查的关键。Spring项目常采用SLF4J(Simple Logging Facade for Java)作为日志接口,它提供了统一的日志记录方法,如info、debug、error等,同时与多种日志实现框架(如Logback、Log4j2)兼容。

除了使用日志框架记录日志外,我们也常常使用如下的方式记录日志:

  • AOP切面编程:定义切面类,通过@Before@AfterReturning@Around等注解在方法执行前后插入日志记录逻辑,灵活且强大,能记录所有请求操作。

  • Filter过滤器:实现jakarta.servlet.Filter接口的类,重写doFilter方法实现日志记录,相比AOP更底层,能获取更多请求信息。很少使用此种方式,因为需要考虑的东西比较多,实现也较为复杂。

  • 自定义拦截器:实现HandlerInterceptor接口,重写preHandle、postHandle等方法记录日志,适用于Spring MVC项目,便于获取请求和响应信息。此种方式想要拿到相关的信息是比较困难的所以,非常简单的日志可以通过此种方式。

     

而关于通过AOP记录日志的方式是用的最多的,AOP允许开发者在不修改业务代码的情况下,将日志记录等横切关注点与业务逻辑分离,实现了日志记录的灵活性和可维护性,极大地提高了开发效率。

尽管AOP功能强大,为Spring项目中的日志记录提供了高效手段,但它并非唯一选择,且由于需要对目标类进行代理,可能会对性能产生一定影响。本篇文章将介绍另一种日志记录方式,该方式无需创建代理,同样能实现完整的日志记录功能。

接下来,我将分别详细介绍基于AOP的日志记录方式以及另一种无需创建代理的日志记录方式,以便进行直观的对比。

2. 实战案例

2.1 基于AOP实现

首先,自定义注解

@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})public @interface Log {
/**模块*/ String module() default "" ; /**具体操作说明*/ String desc() default "" ;}

该注解非常简单,说明当前的操作模块及具体操作说明。

其次,定义切面

@Component@Aspectpublic class LogAspect {
@Pointcut("@annotation(log)") private void recordLog(Log log) {}
@Around("recordLog(log)") public Object logAround(ProceedingJoinPoint pjp, Log log) throws Throwable { String module = log.module(); String desc = log.desc(); long uid = System.nanoTime() ; String threadName = Thread.currentThread().getName(); System.err.printf("%s - 【%d】 模块: %s, 操作: %s, 请求参数: %s%n", threadName, uid, module, desc, Arrays.toString(pjp.getArgs())) ; Object ret = pjp.proceed() ; System.err.printf("%s - 【%d】 返回值: %s%n", threadName, uid, ret) ; return ret ; }}

该切面也非常的简单记录了当前的入参及返回值信息。这里我们设计了一个uid,由于有多个打印,我们以此来跟踪整个链路的请求。如果你对链路跟踪感兴趣那么推荐你查看下面这篇文章:

必学!Spring Boot结合MDC全方位的日志跟踪(支持跨线程)

Spring全家桶实战案例源码
spring, springboot, springcloud 案例开发详解
 最新文章