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

使用AOP完成添加日志

在 Java 中,使用 AOP(面向切面编程)来添加日志是一种常见的做法,特别是当你想要在不修改业务逻辑代码的情况下记录日志时。Spring AOP(Aspect-Oriented Programming)提供了一种简单的方式来实现这一点。以下是如何使用 Spring AOP 来添加日志记录的步骤:

1. 添加依赖

首先,确保你的项目中包含了 Spring AOP 的依赖。如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7.7</version></dependency>
</dependencies>

2. 配置 Aspect

创建一个 Aspect 类来定义你的日志记录逻辑。这个类将包含一个或多个切面(advice),用于在特定的连接点(join points)执行特定的逻辑。

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Pointcut("execution(* com.yourpackage..*(..))")public void logAllMethods() {}@Before("logAllMethods()")public void logBefore(JoinPoint joinPoint) {logger.info("Before the method: {}",joinPoint.getSignature().toShortString());}@AfterReturning(pointcut = "logAllMethods()", returning = "result")public void logAfterReturning(Object result) {logger.info("After the method: {}, Result: {}", joinPoint.getSignature().toShortString(), result);}@AfterThrowing(pointcut = "logAllMethods()")public void logAfterThrowing(JoinPoint joinPoint) {logger.error("Exception in {}",joinPoint.getSignature().toShortString(), joinPoint.getThrowable());}
}

3. 配置 Spring Boot

确保你的 Spring Boot 应用已经启用了 AOP。通常,Spring Boot 会自动配置 AOP,但如果你遇到问题,可以在主应用程序类上添加 @EnableAspectJAutoProxy 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@EnableAspectJAutoProxy
public class YourApplication {public static void main(String[] args) {SpringApplication.run(YourApplication.class, args);}
}

4.如何控制部分方法输出日志?

4.1自定义注解

可以创建自定义注解,并在需要记录日志的方法上使用这些注解。然后在 Aspect 中检查这些注解。

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 Loggable {
}

使用注解

public class YourService {@Loggablepublic void yourMethod() {// 方法逻辑}public void anotherMethod() {// 方法逻辑}
}

 配置 Aspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Pointcut("@annotation(Loggable)")public void logAnnotatedMethods(JoinPoint joinPoint) {try {Object result = joinPoint.proceed();logger.info("Method {} returned {}", joinPoint.getSignature().toShortString(), result);} catch (Throwable throwable) {logger.error("Method {} threw exception", joinPoint.getSignature().toShortString(), throwable);throw throwable;}}
}

4.2 使用表达式语言指定方法

配置 Aspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);// 只记录特定包下的方法@Pointcut("execution(* com.yourpackage..*(..))")public void logMethods() {}@Before("logMethods()")public void logBefore(JoinPoint joinPoint) {logger.info("Before the method: {}", joinPoint.getSignature().toShortString());}@AfterReturning(pointcut = "logMethods()", returning = "result")public void logAfterReturning(Object result) {logger.info("After the method: {}, Result: {}", joinPoint.getSignature().toShortString(), result);}@AfterThrowing(pointcut = "logMethods()")public void logAfterThrowing(JoinPoint joinPoint) {logger.error("Exception in {}", joinPoint.getSignature().toShortString(), joinPoint.getThrowable());}
}

4.3 使用 Spring AOP 注解

可以使用 Spring AOP 提供的注解来指定哪些方法需要记录日志。

定义注解

import org.springframework.stereotype.Component;@Component
public class Loggable {
}

使用注解

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class YourService {@Autowiredprivate Loggable loggable;public void yourMethod() {loggable.log();// 方法逻辑}public void anotherMethod() {// 方法逻辑}
}

配置 Aspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Autowiredprivate Loggable loggable;@Pointcut("execution(* com.yourpackage..*(..))")public void logAllMethods() {}@Before("logAllMethods()")public void logBefore(JoinPoint joinPoint) {logger.info("Before the method: {}", joinPoint.getSignature().toShortString());}@AfterReturning(pointcut = "logAllMethods()", returning = "result")public void logAfterReturning(Object result) {logger.info("After the method: {}, Result: {}", joinPoint.getSignature().toShortString(), result);}@AfterThrowing(pointcut = "logAllMethods()")public void logAfterThrowing(JoinPoint joinPoint) {logger.error("Exception in {}", joinPoint.getSignature().toShortString(), joinPoint.getThrowable());}
}

总结

通过使用注解、表达式语言或 Spring AOP 注解,可以灵活地控制哪些方法需要输出日志,从而实现日志记录的精确控制。这有助于减少不必要的日志输出,提高日志的可读性和维护性。

http://www.xdnf.cn/news/467.html

相关文章:

  • 【AI提示词】IT专家顾问
  • 文件上传及验证绕过漏洞
  • Delphi 常用关键字收录
  • 基础智能体的进展与挑战第 6 章【情绪建模】
  • Python遥感开发之Hurst指数的实现
  • Zookeeper的典型应用场景?
  • Keil MDK中禁用半主机(No Semihosting)
  • 齐次坐标变换+Unity矩阵变换
  • 【Tauri2】026——Tauri+Webassembly
  • 代谢组数据分析(二十四):基于tidymass包从质谱原始数据到代谢物注释结果的实践指南
  • vue3 watch和watchEffect 的用法和区别
  • 计算机视觉算法实现——智能座椅坐姿识别
  • 基于GRPO将QWEN训练为和deepseek一样的推理模型!
  • linux kernel irq相关函数详解
  • 国产的 Java Solon v3.2.0 发布(央企信创的优选)
  • Day10【基于encoder- decoder架构实现新闻文本摘要的提取】
  • 第3章 垃圾收集器与内存分配策略《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
  • 从0开发一个unibest+vue3项目,使用vscode编辑器开发,总结vue2升vue3项目开始,小白前期遇到的问题
  • Flask应用部署通用指南
  • [Windows] Wireshark 网络抓包工具 v4.4.6
  • 【MATLAB海洋专题】历史汇总
  • C++学习之路,从0到精通的征途:vector类的模拟实现
  • 算法期末复习
  • 基于Fabric.js的选座布局系统开发笔记
  • 如何系统地入门学习stm32?
  • Linux419 三次握手四次挥手抓包 wireshark
  • python程序的流程
  • 移动自动化测试-appium
  • thanos rule组件和prometheus区别?
  • 5G基站设计难题:尺寸、重量、功耗和散热