java自定義注解,以編寫spring日志打印注解@ApiLog為例


java自定義注解,以編寫spring日志打印注解@ApiLog為例

1.聲明一個注解

基本元素 描述
修飾符 訪問修飾符必須為public,不寫默認為pubic
關鍵字 關鍵字為@interface
注解名稱 注解名稱為自定義注解的名稱,使用時還會用到
注解類型元素 注解類型元素是注解中內容,可以理解成自定義接口的實現部分

例:

public @interface ApiLog {
}

2.@Target修飾注解

@Target用以表明該注解可以應用的java元素類型

類型 描述
ElementType.TYPE 應用於類、接口(包括注解類型)、枚舉
ElementType.FIELD 應用於屬性(包括枚舉中的常量)
ElementType.METHOD 應用於方法
ElementType.PARAMETER 應用於方法的形參
ElementType.CONSTRUCTOR 應用於構造函數
ElementType.LOCAL_VARIABLE 應用於局部變量
ElementType.ANNOTATION_TYPE 應用於注解類型
ElementType.PACKAGE 應用於包
ElementType.TYPE_PARAMETER 1.8版本新增,應用於類型變量
ElementType.TYPE_USE 1.8版本新增,應用於任何使用類型的語句中(例如聲明語句、泛型和強制轉換語句中的類型)

例:

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ApiLog {
}

3.@Retention修飾注解

類型 描述
RetentionPolicy.SOURCE 編譯時被丟棄,不包含在類文件中
RetentionPolicy.CLASS JVM加載時被丟棄,包含在類文件中,默認值
RetentionPolicy.RUNTIME 由JVM 加載,包含在類文件中,在運行時可以被獲取到

例:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {
}

4.@Document修飾注解

@Document表明該注解標記的元素可以被Javadoc 或類似的工具文檔化

例:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLog {
}

5.@Inherited修飾注解

表明使用了@Inherited注解的注解,所標記的類的子類也會擁有這個注解

例:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ApiLog {
}

6.編寫@ApiLog的實現切面類

例:

@Component
@Aspect
@Slf4j
public class MyApiLogAspect {

    @Pointcut("@annotation(boss.xtrain.log.api.ApiLog) || @within(boss.xtrain.log.api.ApiLog)")
    public void pointCut() {
        // 切點
    }

    /**
     * @description 打印請求報文和應答報文
     * @params [joinPoint]
     * @return java.lang.Object
     */
    @Around("pointCut()")
    public Object saveLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 獲取當前時間
        long reqTime = System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTime = sdf.format(new Date(reqTime));
        // 獲取請求ip
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteAddr();
        // 獲取調用方法和參數
        String method = joinPoint.getSignature().getDeclaringType() + "." + joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        // 獲取全局流水號,全局流水號為本業務需要,若無請省略
        Class<?> tmpClass = args[0].getClass();
        Field field = tmpClass.getDeclaredField("globalMessageNo");
        field.setAccessible(true);
        Object gMessageNoObj = field.get(args[0]);
        String gMessageNoStr = null;
        if (null != gMessageNoObj) {
            gMessageNoStr = (String) gMessageNoObj;
        }
        // 打印請求報文
        log.info("請求報文:流水號:{} # 時間:{} # ip:{} # 調用方法:{} # 請求參數:>>>>>>>>>>{}", gMessageNoStr, currentTime, ip, method, args);
        // 獲取應答結果
        Object result = null;
        result = joinPoint.proceed();
        // 獲取處理時間
        long respTime = System.currentTimeMillis() - reqTime;
        // 打印應答報文
        log.info("應答報文:流水號:{} # 時間:{} # 響應時間:{}ms # 返回參數:<<<<<<<<<<{}", gMessageNoStr, currentTime, respTime, result);
        return result;
    }

}

參考博客:https://blog.csdn.net/zt15732625878/article/details/100061528


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM