重庆平台网站建设企业博客制作
2026/5/31 23:04:54 网站建设 项目流程
重庆平台网站建设企业,博客制作,推广策略研究,山东泰安天气预报一周AOP 日志记录实战 1. 概述 本文主要介绍基于 Spring AOP 的 5 种通知类型实现统一日志记录的代码实战。 关于 AOP 的核心理论概念#xff0c;请参考笔记 [[AOP面向切面编程]]。 核心思路#xff1a; 通过自定义注解标记需要记录日志的业务方法#xff0c;利用 AOP 切面拦…AOP 日志记录实战1. 概述本文主要介绍基于 Spring AOP 的5 种通知类型实现统一日志记录的代码实战。关于 AOP 的核心理论概念请参考笔记 [[AOP面向切面编程]]。核心思路通过自定义注解标记需要记录日志的业务方法利用 AOP 切面拦截带有该注解的方法在方法执行的不同阶段前置、后置、异常、环绕输出日志信息。2. 环境准备2.1 定义目标方法为了演示效果我们先定义一个简单的 Controller 或 Service 方法作为连接点Join Point。2.2 自定义注解创建自定义注解AopLogText用于标记切入点并传递业务描述参数。相关基础知识可参考 [[自定义注解]]。packagecom.example.annotation;importjava.lang.annotation.*;Target(ElementType.METHOD)// 作用范围方法Retention(RetentionPolicy.RUNTIME)// 生命周期运行时保留关键否则AOP无法通过反射获取DocumentedpublicinterfaceAopLogText{/** * 业务描述信息 * 例如AopLogText(用户登录) */Stringvalue()default;}3. 切面类实现创建一个切面类用于封装日志处理逻辑。核心注解说明Aspect: 标记该类为一个切面类。Component: 将该类注册到 Spring 容器中使其生效。Slf4j: (可选) Lombok 注解用于快速使用日志对象log。3.1 定义切入点这里直接使用Pointcut定义通用的匹配规则或者在通知注解中直接写表达式。本例主要演示基于注解的切入方式annotation(com.example.annotation.AopLogText)。4. 通知类型详解与代码4.1 前置通知 (Before)在目标方法执行之前触发。常用于记录“开始执行某动作”及入参信息。/** * 前置通知 * param joinPoint 连接点对象可获取方法签名、参数等信息 * param aopLog 注解对象通过参数绑定直接获取注意参数名需匹配 */Before(annotation(aopLog))publicvoidbeforeMethod(JoinPointjoinPoint,AopLogTextaopLog){// 1. 获取目标方法名StringmethodNamejoinPoint.getSignature().getName();// 2. 获取注解上的参数值 (如: 开始查询)StringannotationValueaopLog.value();log.info([前置通知] 准备执行方法{}业务描述{},methodName,annotationValue);}4.2 返回通知 (AfterReturning)在目标方法正常返回后触发。可以获取方法的返回值。注意如果方法抛出异常此通知不会执行。/** * 返回通知 * param joinPoint 连接点 * param result 目标方法的返回值 (参数名必须与 returning 属性一致) */AfterReturning(valueannotation(com.example.annotation.AopLogText),returningresult)publicvoidafterReturning(JoinPointjoinPoint,Objectresult){StringmethodNamejoinPoint.getSignature().getName();log.info([返回通知] 方法 {} 执行完成返回值{},methodName,result);}4.3 异常通知 (AfterThrowing)在目标方法抛出异常时触发。可以获取具体的异常对象。/** * 异常通知 * param joinPoint 连接点 * param ex 抛出的异常对象 (参数名必须与 throwing 属性一致) */AfterThrowing(valueannotation(com.example.annotation.AopLogText),throwingex)publicvoidafterThrowing(JoinPointjoinPoint,Exceptionex){StringmethodNamejoinPoint.getSignature().getName();log.error([异常通知] 方法 {} 执行异常原因{},methodName,ex.getMessage());}4.4 最终通知 (After)在目标方法执行之后触发。特点无论方法是正常结束还是抛出异常都会执行类似于try-catch-finally中的finally块。After(annotation(com.example.annotation.AopLogText))publicvoidafterMethod(JoinPointjoinPoint){StringmethodNamejoinPoint.getSignature().getName();log.info([最终通知] 方法 {} 执行结束无论是否异常,methodName);}4.5 环绕通知 (Around)功能最强大的通知类型。它包裹了目标方法可以在方法执行前后自定义逻辑甚至控制方法是否执行、修改返回值。适用场景统计方法耗时、统一异常处理、事务控制。/** * 环绕通知 * param joinPoint ProceedingJoinPoint 是 JoinPoint 的子接口增加了 proceed() 方法 * param aopLogText 注解对象 * return 目标方法的返回值 (必须返回否则调用方收不到数据) */Around(annotation(aopLogText))publicObjectaroundMethod(ProceedingJoinPointjoinPoint,AopLogTextaopLogText)throwsThrowable{StringmethodNamejoinPoint.getSignature().getName();StringannotationValueaopLogText.value();log.info(【环绕通知】开始执行方法{}注解参数{},methodName,annotationValue);longstartTimeSystem.currentTimeMillis();Objectresultnull;try{// 核心执行目标方法// result 为目标方法的返回值resultjoinPoint.proceed();}catch(Throwablee){log.error(【环绕通知】方法 {} 执行异常{},methodName,e.getMessage());// 注意通常需要将异常抛出否则上层如全局异常处理器无法感知throwe;}finally{longcostTimeSystem.currentTimeMillis()-startTime;log.info(【环绕通知】方法 {} 执行耗时{}ms,methodName,costTime);}// 必须返回结果returnresult;}5. 关键细节参数绑定在 AOP 中获取注解参数时有一种简便的参数绑定写法无需通过反射手动解析。操作步骤在切入点表达式中指定参数名例如annotation(aopLog)。在通知方法的参数列表中声明同名的参数AopLogText aopLog。示意图注意事项切面方法中的参数名如aopLog必须与注解表达式annotation(aopLog)中的名称严格一致否则 Spring 无法完成映射。6. 最佳实践在实际项目中应根据需求选择合适的通知类型基础日志记录推荐组合使用Before记录入参、AfterReturning记录返回值和AfterThrowing记录异常。优点职责单一代码逻辑清晰解耦性好。复杂场景 / 性能监控推荐使用Around。场景需要统计方法耗时Start Time - End Time、需要改变返回值、或者需要在一个上下文中同时处理入参和结果。避免滥用Around虽然环绕通知功能最强但如果只是简单的打印日志使用组合通知的可读性更高。环绕通知需要手动调用proceed()并处理异常编写不当容易导致目标方法不执行或异常被吞没。进阶扩展在生产环境中通常会将日志信息操作人、时间、IP、耗时、结果异步存储到数据库或发送到ELK(Elasticsearch, Logstash, Kibana) 系统中以便进行审计和分析。7. 参考文章与学习来源参考文章Spring AOP 实现日志记录案例详解知识问答亲爱的豆包老师笔记/术语优化gemini-3-pro-preivew

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询