自定義日誌註解(可獲取方法名、參數等)

這裏主要依賴了spring的AOP來實現的,如果沒有引用spring的,不可以使用這種方式。

一、引入依賴

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

 <dependency>
     <groupId>org.apache.commons</groupId>
     <artifactId>commons-lang3</artifactId>
     <version>3.9</version>
 </dependency>

二、自定義日誌註解

package com.example.demo.log;

import java.lang.annotation.*;

/**
 * 日誌通過startLog、endLog、errorLog三個字段控制,如果想簡單些, 可以只出入operate
 * startLog:方法進入時的日誌
 * endLog:方法執行完之後的日誌
 * errorLog:錯誤日誌
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperateLog {

    String startLog() default ""; // 方法開始執行前日誌

    String endLog() default ""; // 方法結束執行日誌

    String operate() default "";//操作

    String errorLog() default "";//錯誤日誌

}

三、創建日誌註解解析類

package com.example.demo.log;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 日誌註解解析器,日誌可以異步保存到數據庫,這裏只是打印了而已,
 */
@Aspect
@Component
@Slf4j
public class OperateLogResolver {

    /**
     * 切點
     */
    private final String EXECUTION = "@annotation(com.example.demo.log.OperateLog)";

    @Around(EXECUTION)
    public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {

        //獲取要執行的方法
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();

        String className = joinPoint.getSignature().getDeclaringTypeName();

        String methodName = String.format("%s.%s", className, method.getName());

        //獲取註解信息
        OperateLog upgradeProgress = method.getAnnotation(OperateLog.class);

        String operate = upgradeProgress.operate(); // 當前操作

        //開始日誌
        String startLog = StringUtils.defaultIfBlank(upgradeProgress.startLog(), StringUtils.isNotEmpty(operate) ? String.format("start %s", operate) : String.format("start execute %s", methodName));

        //結束日誌
        String endLog = StringUtils.defaultIfBlank(upgradeProgress.endLog(), StringUtils.isNotEmpty(operate) ? String.format("execute %s successfully", operate) : String.format("execute %s successfully", methodName));

        //錯誤日誌
        String errorLog = StringUtils.defaultIfBlank(upgradeProgress.errorLog(), StringUtils.isNotEmpty(operate) ? String.format("execute %s error", operate) : String.format("execute %s error", methodName));


        //記錄方法執行前日誌
        log.info(startLog);

        //獲取方法信息
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); //參數名

        // 參數值:
        final Object[] argValues = joinPoint.getArgs();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < argNames.length; i++) {
            String value = argValues[i] == null ? "null" : argValues[i].toString();
            sb.append(argNames[i]).append("=").append(value).append(",");
        }
        String paramStr = sb.length() > 0 ? sb.toString().substring(0, sb.length() - 1) + "]" : "";
        log.info("參數信息爲:[ {}", paramStr);

        //執行方法
        Object result = null;

        try {
            result = joinPoint.proceed();
        } catch (Exception e) {
            log.error(errorLog, e);

        }

        String resultStr = result == null ? "null" : result.toString();
        log.info("返回結果爲:{}",resultStr);

        //記錄方法執行後日志
        log.info(endLog);

        return result;
    }

}

四、使用日誌註解

@OperateLog(
         operate = "update user"
 )
 public User updateUser(User user,String greet) {
     System.out.println(greet);
     user.setAge(user.getAge() + 2);
     user.setName(StringUtils.defaultIfBlank("NULL NAME", StringUtils.upperCase(user.getName())));
     return user;
 }

打印的日誌信息內容如下:

2019-11-11 20:31:48.004  INFO 10856 --- [nio-8080-exec-1] com.example.demo.log.OperateLogResolver  : start update user
2019-11-11 20:31:48.005  INFO 10856 --- [nio-8080-exec-1] com.example.demo.log.OperateLogResolver  : 參數信息爲:[ user=User(name=liuxing, age=20),greet=hello]
hello
2019-11-11 20:31:48.019  INFO 10856 --- [nio-8080-exec-1] com.example.demo.log.OperateLogResolver  : 返回結果爲:User(name=NULL NAME, age=22)
2019-11-11 20:31:48.019  INFO 10856 --- [nio-8080-exec-1] com.example.demo.log.OperateLogResolver  : execute update user successfully

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章