java日志注解:无中生有,到底算不算优化

本文介绍了一种在现有代码基础上优化接口调用日志的方法,通过在接口入参中加入日志信息类参数,实现了记录修改人、时间、主键ID及入参和出参的功能,探讨了此方法对后期维护的影响。

最近在项目版本迭代中又一个这样的需求:
在已有的代码基础上添加接口调用日志,记录的日志内容主要针对的是修改记录的接口:
1、表数据的修改人,
2、修改的时间,
3、修改的记录的主键id,
4、接口的入参和出参。
通过注解我们很容易就能拿到接口的入参,出参,接口调用时间,接口的修改人,
但是唯独一个修改的记录对应的主键id这个东西不好处理,虽然接口入参中会有对应的id参数,但是却不好提取。。。考虑了一番后,在保证不做大量的改动前提上,
想出了一个解决方法-------》在接口的入参上加上日志信息类参数

无中生有的操作就开始了,最终切面完成后的效果就是直接在方法上添加@Log,并且在入参上添加LogInfo,这个参数会直接在切面中实例化,方法上只需要直接往logInfo塞数据就行了

// 注解类
import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    int targetId() default 0;
    String apiName() default "";
    int option() default 0;
}

import club.reedlu.www.boot.common.annotation.Log;
import club.reedlu.www.boot.common.vo.LogInfo;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class LogImpl {

    @Pointcut("@annotation(club.reedlu.www.boot.common.annotation.Log)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object arround(ProceedingJoinPoint joinPoint) {
        // 内部实例化logInfo
        LogInfo logInfo = new LogInfo();
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        Class<?>[] parameterTypes = method.getParameterTypes();
        Object[] args = joinPoint.getArgs();
        Map<String,Object> map = new HashMap<>();
        for(int i=0;i<parameterTypes.length;i++){
            if(parameterTypes[i] == LogInfo.class){
                if(args[i] == null){
                    // 如果取到的参数为null就用切面中的参数
                    args[i] = logInfo;
                }else{
                    // 如果取到的值不为null就用接口的入参
                    logInfo = (LogInfo) args[i];
                }
            }else{
                map.put(parameterTypes[i].getName(),args[i]);
            }
        }
        Log logAnnotation = method.getAnnotation(Log.class);
        logInfo.setApiName(logAnnotation.apiName());
        logInfo.setTargetId(logAnnotation.targetId());
        // 将入参转化为json字符串
        logInfo.setParam(JSONObject.toJSONString(map));
        Object result = null;
        // 记录开始时间
        long start = System.currentTimeMillis();
        try {
            result = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 记录结束时间
        long end = System.currentTimeMillis();
        // 记录接口调用时间
        logInfo.setTime(end-start);
        // 如果返回值在方法中已经设置类,就不再手动设置
        if(StringUtils.isEmpty(logInfo.getResult())){
            logInfo.setResult(JSONObject.toJSONString(result));
        }
        // 异步执行记录日志sql
        System.out.println(logInfo);
        return result;
    }
}

在使用上的变化就是

从最开始的接口

    @Override
    public String sayHello() {
        return "hello";
    }

下面是记录日志的接口:

@Override
    @Log(apiName = "sayHello")
    public String sayHello(LogInfo logInfo) {
        logInfo.setOption(1001);
        // 记录修改对象对应的主键id
        logInfo.setTargetId(1);
        return "hello";
    }

这种做法虽然解决了问题,但是这种无中生有的操作对于后期维护并不友好,我也不知道这种做法算不算是优化了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值