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

使用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 注解,可以灵活地控制哪些方法需要输出日志,从而实现日志记录的精确控制。这有助于减少不必要的日志输出,提高日志的可读性和维护性。

相关文章:

  • 文件系统基础
  • P1113 杂务-拓扑排序
  • gulp方法
  • Linux——firewalld防火墙(笔记)
  • 关于一对多关系(即E-R图中1:n)中的界面展示优化和数据库设计
  • 可以直接本地使用的Python环境可以调用的AI大模型归纳整理(AI辅助)
  • Linux学习——信号量
  • 编程技能:调试04,逐语句命令
  • JavaScript数据类型简介
  • [Java]反射、String类补充
  • SICAR程序标准功能块 FB1512 “Robot_kuka_FB“
  • 02、Yarn的安装理念及如何破解依赖管理困境
  • Photoshop安装与配置--简单攻略版
  • 【教程】DVWA靶场渗透
  • 【无标题】微信开发者工具编译运行没问题,真机调试报错:Component is not found in path “wx://not-found“.
  • JavaScript 中的同步与异步:从单线程到事件循环
  • 睡前小故事数据集分享
  • 企业微信自建应用开发回调事件实现方案
  • javaNIO详解
  • cv::dnn::NMSBoxes和nms-free的比较
  • 南部战区海军新闻发言人发表谈话
  • 上海群文创作大检阅,102个节目角逐群星奖
  • 调查显示特朗普在经济问题上的支持率跌至其总统生涯最低
  • 潮州官方回应女婴事件:尚未发现虐待,各种原因导致营养不良
  • 重庆网红景点“莲花茶摊”被市民投诉,官方:采纳意见,整改!
  • 瑞士工业巨头ABB拟分拆机器人业务独立上市,市场份额全球第二