aop 日志增强处理并修改返回

接手同事的工作,由于很多模块都是刚写的没做测试,代码里也没有做错误日志记录,测试一直报bug,但测试环境又不能看出哪报错,无从下手。一个一个方法加日志处理加起来太麻烦,就想着能不能调用统一处理。

那这个概念就和aop 切面不谋而合。

AOP介绍:
spring aop英文文档
AOP:Aspect-Oriented Programming的缩写
JoinPoint:要切入的点,具体的方法。
Pointcut: 符合条件的Joinpoint集合。
Aspect:切面,即封装了切入面和切入点的模块,例如我们要做的日志处理,就是切面。
Advice:切点如何处理,什么时候处理(之前、之后、环绕等等)。

poincut放在controller中,开始打算使用 After throwing advice,可以对系统中没做处理的抛出进行增强处理,但项目中需要返回自定义响应数据实体类,以显示请求状态,joinpoint方法出现抛出异常后无法正常返回,显然无法满足需求。

那哪些advice 适合呢?下面同样是官方文档相关内容

Before advice: Advice that executes before a join point, but which does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).

After returning advice: Advice to be executed after a join point completes normally: for example, if a method returns without throwing an exception.

After throwing advice: Advice to be executed if a method exits by throwing an exception.

After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).

Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

这是最有力的advice。可以在方法调用之前之后执行自定义行为。它还可以选择继续执行连接点或返回其自身的返回值或引发异常来快速建立方法执行。
如上,around可以很好的满足我们的需求。

下面是一些具体示例,主要展示一些大体框架,至于对于错误日志是入库还是怎么处理,看个人具体需求。

pring 配置

<aop:aspectj-autoproxy/>//开注解 @AspectJ Support

注解方式实现:

package com.test.test;

import com.common.util.ResponseDataUtil;
import org.apache.poi.ss.formula.functions.T;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Aspect
@Component
public class errorLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(logAspect.class);
	//controller的包名,所有返回自定义响应的方法
    @Pointcut("execution(com.ResponseData<*>  com.test.test..* (..))")
    public void pointCut() {
    }
    
    /**
     * 环绕方式方便修改返回值
     * @param jp
     * @return
     */
    @Around("pointCut()")
    public ResponseData<T> handlerAround(ProceedingJoinPoint jp){
        try {
            return (ResponseData<T>)jp.proceed();//反射执行目标对象的连接点处的方法,可修改入参
        } catch (Throwable e) {
            Object[] args = jp.getArgs();//参数
            String className = ((MethodSignature) jp.getSignature()).getMethod().getDeclaringClass().getName();//类名
            String funcName = jp.getSignature().getName();//方法名
            StringBuilder sb = new StringBuilder("调用"+ className +" 的"+ funcName+" 方法异常。方法入参:"+Arrays.toString(args));
            logger.error(sb.toString(), e);
            return ResponseDataUtil.getFailResponse("内部错误" + e.getMessage());
            }
        }
    }

总的来说,学会面向文档编程吧,学会啃文档。另外业务上不要把异常处理等代码和业务代码混杂在一起,减少重复代码并且让业务主逻辑更清晰明了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值