Spring Boot 使用自定义注解和自定义线程池实现异步日志记录

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
💕《Jenkins实战》专栏主要介绍Jenkins+Docker+Git+Maven的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

Spring Boot 使用自定义注解和自定义线程池实现异步日志记录

  • 1、前言
  • 2、异步日志记录的重要性
    • 2.1 提高性能
    • 2.2 减少延迟
    • 2.3 提升稳定性
    • 2.4 资源管理优化
  • 3、开始构建
    • 3.1 创建 Spring Boot 项目
    • 3.2 创建自定义注解类
    • 3.3 配置自定义线程池
    • 3.4 编写日志记录切面
    • 3.5 编写Controller中使用@LogAsync
  • 4、接口测试
  • 5、结语

1、前言

在我们日常开发工作中,日志记录是至关重要的部分。它不仅有助于调试和故障排除,还能提供系统运行的历史记录,帮助进行性能优化和安全监控。然而,日志记录也可能对系统性能产生影响,特别是在高并发环境下。因此,使用异步日志记录技术可以有效地提升系统性能和可靠性。

博主将带着大家一起探讨 Spring Boot 异步日志记录的优雅实现方法。

2、异步日志记录的重要性

2.1 提高性能

在传统的同步日志记录方式中,每次日志记录操作都需要等待日志写入完成,才能继续执行后续操作。这种方式在高并发环境下会导致明显的性能瓶颈。异步日志记录通过将日志写入操作放入独立的线程中执行,避免了主线程的阻塞,从而大幅提高了系统的整体性能。

2.2 减少延迟

在需要快速响应的应用程序中,如实时系统或高频交易系统,任何形式的延迟都会影响系统的响应时间。异步日志记录能将日志记录操作从主业务流程中剥离出来,减少了响应时间,提升了用户体验。

2.3 提升稳定性

在高负载情况下,同步日志记录可能会导致系统资源的争用,影响系统的稳定性。异步日志记录通过使用独立的线程池管理日志写入操作,避免了这种资源争用,提高了系统的稳定性和可靠性。

2.4 资源管理优化

异步日志记录允许更灵活地管理系统资源。通过配置线程池的大小和任务队列,可以更好地控制系统资源的使用,避免了因为日志记录过多导致的内存和磁盘 I/O 资源耗尽问题。

3、开始构建

3.1 创建 Spring Boot 项目

可以使用 Spring Initializr 创建项目,确保在 pom.xml 文件中添加了必要的依赖:

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter AOP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
</dependencies>

3.2 创建自定义注解类

定义一个自定义注解类 LogAsync 用于标记需要异步记录的日志方法,并且系统会记录功能组、操作人、方法名、传递的参数等(仅模拟,大家根据自己项目需求定制)
代码如下:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAsync {// 可以根据需要添加属性 比如功能组String funGroup() default "";
}

3.3 配置自定义线程池

为了优化异步日志记录,我们需要配置一个自定义线程池

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;@Configuration
@EnableAsync
public class AsyncConfig{@Bean(name = "logExecutor")public Executor logExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);executor.setThreadNamePrefix("LogExecutor-");executor.initialize();return executor;}
}

3.4 编写日志记录切面

创建一个AOP切面 LoggingAspect 来处理异步日志记录

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.Executor;@Aspect
@Component
@Slf4j
public class LoggingAspect {private final Executor logExecutor;public LoggingAspect(@Qualifier("logExecutor") Executor logExecutor) {this.logExecutor = logExecutor;}@Pointcut("@annotation(LogAsync)")public void loggableMethods() {}@AfterReturning(pointcut = "loggableMethods()", returning = "result")@Async("logExecutor")public void logMethodCall(JoinPoint joinPoint, Object result) {//获取注解类LogAsync logAsync = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(LogAsync.class);//获取注解上的功能组String funGroup = logAsync.funGroup();//获取方法名String methodName = joinPoint.getSignature().getName();//获取参数Object[] args = joinPoint.getArgs();//方法返回结果  Object resultlog.info("funGroup: {}, Method: {}, Args: {}, Result: {}", funGroup, methodName, args, result);//TODO 这里可以加入日志入库操作}
}

3.5 编写Controller中使用@LogAsync

创建一个TestUser类,作为接收参数

import lombok.Data;@Data
public class TestUser {private String username;private String password;
}

创建 LogSampleController ,标注@LogAsync注解

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api")
public class LogSampleController {/*** 模拟保存* @param user 自定义用户类* @return*/@LogAsync(funGroup = "用户模块")@PostMapping("/save-user")public ResponseEntity<String> saveUser(@RequestBody  TestUser user) {return new ResponseEntity<>("操作成功", HttpStatus.OK);}
}

4、接口测试

运行 Spring Boot 应用程序,使用测试工具访问 http:/your_host/api/save-user。观察控制台中可以看到异步日志记录的信息
在这里插入图片描述
控制台输出:
在这里插入图片描述

温馨提示
演示代码中,博主是获取 功能组、方法名、传递的参数、返回结果;
正常我们日志记录还会有很多主要信息,比如:操作人、修改前数据、修改后数据、修改时间等等,大家可以根据自己系统情况进行调整

5、结语

通过自定义注解Spring AOP自定义线程池,我们可以在 Spring Boot 应用中实现高效的异步日志记录。这种方法不仅提高了日志记录的灵活性,还能减小对主业务线程的影响。希望本文对您在实际项目中实现日志记录有所帮助。

这种方式在实际生产环境中非常实用,特别是在需要高效处理大量日志记录的场景下。通过合理配置线程池,可以确保日志记录的性能和稳定性。


在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树-二叉树的最大路径和

一、问题描述 二、解题思路 因为各个节点的值可能为负数&#xff0c;初始化res(最大路径和)的值为最小整数&#xff1a;Integer.MIN_VALUE 我们这里使用深度遍历&#xff08;递归&#xff09;的方法&#xff0c;先看某一个子树的情况&#xff1a; 这里有一个技巧&#xff0c;…

纷享销客安全体系:安全运维运营

安全运维运营(Security Operations,SecOps)是指在信息安全管理中负责监控、检测、响应和恢复安全事件的一系列运营活动。它旨在保护组织的信息系统和数据免受安全威胁和攻击的损害。 通过有效的安全运维运营&#xff0c;组织可以及时发现和应对安全威胁&#xff0c;减少安全事…

【Linux文件篇】系统文件、文件描述符与重定向的实用指南

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#xff1a;相信大家对文件都不会太陌生、也不会太熟悉。在没有学习Linux操作系统时&#xff0c;我们在学习C或C时都学过如何去创建、打开、读写等待文件的操作&#xff0c;知道一些语言级别的一些接口与函数。但…

【Pytorch】一文向您详细介绍 torch.tensor() 的常见用法

【Pytorch】一文向您详细介绍 torch.tensor() 的常见用法 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通…

盲盒小程序推广与运营策略的挑战

随着盲盒经济的兴起&#xff0c;越来越多的商家开始关注并尝试开发盲盒小程序。然而&#xff0c;在推广和运营盲盒小程序的过程中&#xff0c;我们也不可避免地会遇到一些挑战。下面&#xff0c;我将就用户获取、留存以及活跃度提升等方面&#xff0c;探讨这些挑战及可能的应对…

【Linux】生产者消费者模型——阻塞队列BlockQueue

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;理解【Linux】生产者消费者模型——阻塞队列BlockQueue。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安!…

【网络安全】网络安全基础精讲 - 网络安全入门第一篇

目录 一、网络安全基础 1.1网络安全定义 1.2网络系统安全 1.3网络信息安全 1.4网络安全的威胁 1.5网络安全的特征 二、入侵方式 2.1黑客 2.1.1黑客入侵方式 2.1.2系统的威胁 2.2 IP欺骗 2.2.1 TCP等IP欺骗 2.2.2 IP欺骗可行的原因 2.3 Sniffer探测 2.4端口扫描技术…

知识付费小程序源码系统 一键拥有属于自己的知识店铺 带完整的安装代码包以及搭建教程

系统概述 在数字化时代&#xff0c;知识已成为最具价值的资产之一。随着互联网技术的飞速发展&#xff0c;知识付费市场迎来了前所未有的发展机遇。为了帮助广大内容创作者、教育机构及个人轻松搭建专属的知识店铺&#xff0c;一款高效、易用的知识付费小程序源码系统应运而生…

架构设计-用户信息及用户相关的密码信息设计

将用户的基本信息和用户密码存放在不同的数据库表中是一种常见的安全做法&#xff0c;这种做法旨在增强数据的安全性和管理的灵活性。以下是这种做法的几个关键原因&#xff1a; 安全性增强&#xff1a; 当用户密码被单独存放在一个表中时&#xff0c;可以使用更强大的加密和哈…

超详解——Python模块文档——基础篇

目录 1. Unix起始行 示例&#xff1a; 2. 对象和类型 示例&#xff1a; 3. 一切都是对象 示例&#xff1a; 4. 理解对象和引用 示例&#xff1a; 5. 理解对象和类型 示例&#xff1a; 6. 标准类型 示例&#xff1a; 7. 其他内建类型 示例&#xff1a; 8. 类型的类…

东南亚电商Tiki、Qoo10:如何用自养号测评提升产品曝光和销量

随着互联网的普及和全球化的推进&#xff0c;跨境电商在东南亚地区日益繁荣。Tiki、Qoo10作为该地区的电商巨头&#xff0c;不仅吸引了大量消费者&#xff0c;也成为了卖家竞相角逐的战场。为了在这场竞争中脱颖而出&#xff0c;卖家们纷纷采用测评这一方式来提升产品销量。本文…

弱智吧”,人类抵御AI的最后防线

“写遗嘱的时候错过了deadline怎么办&#xff1f;” “怀念过去是不是在时间的长河里刻舟求剑&#xff1f;” “英语听力考试总是听到两个人在广播里唠嗑&#xff0c;怎么把那两个干扰我做题的人赶走&#xff1f;” 以上这些饱含哲学但好像又莫名其妙的问题&#xff0c;出自…

MySQL复习题(期末考试)

MySQL复习题&#xff08;期末考试&#xff09; 1.MySQL支持的日期类型&#xff1f; DATE,DATETIME,TIMESTAMP,TIME,TEAR 2.为表添加列的语法&#xff1f; alter table 表名 add column 列名 数据类型; 3.修改表数据类型的语法是&#xff1f; alter table 表名 modify 列名 新…

在windows10 安装子系统linux(WSL安装方式)

在 windows 10 平台采用了WSL安装方式安装linux子系统 1 查找自己想要安装的linux子系统 wsl --list --online 2 在线安装 个人用Debian比较多&#xff0c;这里选择Debian&#xff0c;如下图&#xff1a; wsl --install -d Debian 安装过程中有一步要求输入用户名与密码&…

LNMP与动静态网站介绍

Nginx发展 Nginx nginx http server Nginx是俄罗斯人 Igor Sysoev(伊戈尔.塞索耶夫)开发的一款高性能的HTTP和反向代理服务器。 Nginx以高效的epoll.kqueue,eventport作为网络IO模型&#xff0c;在高并发场景下&#xff0c;Nginx能够轻松支持5w并发连接数的响应&#xff0c;并…

【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用

&#x1f525; 个人主页&#xff1a;空白诗 &#x1f525; 热门专栏&#xff1a;【Go语言精进之路】 文章目录 引言一、切片究竟是什么&#xff1f;1.1 基础的创建数组示例1.2 基础的创建切片示例1.3 切片与数组的关系 二、切片的高级特性&#xff1a;动态扩容2.1 使用 append …

分布式一致性理论

分布式一致性理论 1.数据库事务ACID理论 为保证事务正确可靠而必须具备的四个核心特性。这四个特性分别是&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;D…

社交创新:Facebook的技术与产品发展

在当今数字化时代&#xff0c;社交网络已经渗透到我们生活的方方面面&#xff0c;成为了人们日常交流、信息获取和社交互动的主要方式。而在这个众多社交平台中&#xff0c;Facebook作为其中的佼佼者&#xff0c;其技术与产品的发展历程也是一个社交创新的缩影。本文将探索Face…

六、【源码】SQL执行器的定义和实现

源码地址&#xff1a;https://github.com/mybatis/mybatis-3/ 仓库地址&#xff1a;https://gitcode.net/qq_42665745/mybatis/-/tree/06-sql-executor SQL执行器的定义和实现 之前的Sql执行都是耦合在SqlSession里的&#xff0c;现在要对这部分进行解耦和重构&#xff0c;引…

《软件定义安全》之三:用软件定义的理念做安全

第3章 用软件定义的理念做安全 1.不进则退&#xff0c;传统安全回到“石器时代” 1.1 企业业务和IT基础设施的变化 随着企业办公环境变得便利&#xff0c;以及对降低成本的天然需求&#xff0c;企业始终追求IT集成设施的性价比、灵活性、稳定性和开放性。而云计算、移动办公…