Aop示例之注解切面方式實現日志打印


在使用切面前,首先保證項目配置啟動對@AspectJ注解的支持及監聽類,在Spring的配置文件中,添加如下配置即可:

<!-- 啟動對@AspectJ注解的支持  -->
<aop:aspectj-autoproxy proxy-target-class="true" />

 

示例:

 

import cn.hutool.json.JSONUtil;
import com.credithc.openapi.flowplatform.basedto.BaseResp;
import com.credithc.openapi.flowplatform.enums.ResultCodeEnum;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 針對base服務模塊api的日志打印切面
 *
 * @author kuangxiang
 * @date 2020/10/27 10:55
 */
@Aspect
@Component
public class LogForBaseApiAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 定義切點
     * <p>
     * 作用是供通知方法知道需要在何處執行通知
     * execution:可以是個包路徑,例如本示例中;也可以是自定義的注解
     * </P>
     */
    @Pointcut("execution(* com.credithc.openapi.flowplatform.dubboapi.*.*(..)) || " +
            "execution(* com.credithc.openapi.flowplatform.service.impl.*.*(..)) || " +
            "execution(* com.credithc.openapi.flowplatform.controller.*.*(..))")
    public void point() {
    }

    /**
     * 環繞通知
     * <p>
     * 1.在目標方法執行前和執行后都會執行此方法
     * 2.接口中的參數對應ProceedingJoinPoint而不是JoinPoint,是因為 ProceedingJoinPoint繼承了JoinPoint是在JoinPoint的基礎上暴露出proceed 這個方法 ,
     * 執行proceed方法的作用是讓目標方法執行,這也是環繞通知和前置、后置通知方法的一個最大區別。
     * </P>
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("point()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        String substring = className.substring(className.lastIndexOf(".") + 1);
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        String methodName = signature.getName();
        Object[] args = proceedingJoinPoint.getArgs();

        logger.info("【流量增益平台】【{}.{}】請求開始,req:{}", substring, methodName, Arrays.toString(args));

        long beginTime = System.currentTimeMillis();
        // 執行方法
        Object result = proceedingJoinPoint.proceed();
        // 執行時長(毫秒)
        long costTime = System.currentTimeMillis() - beginTime;

        logger.info("【流量增益平台】【{}.{}】請求結束,req:{},result:{},執行時間:【{}】毫秒", className, methodName, Arrays.toString(args),
                JSONUtil.toJsonStr(result), costTime);
        return result;
    }

    /**
     * 目標方法執行前執行
     *
     * @param joinPoint 切點對象
     */
    @Before("point()")
    public void before(JoinPoint joinPoint) {

    }

    /**
     * 目標方法正常結束后執行
     *
     * @param joinPoint 切點對象
     * @param resp      這個參數定義目標方法響應結果參數名,和@AfterReturning注解中returening屬性的值是一致的
     */
    @AfterReturning(returning = "resp", pointcut = "point()")
    public void afterReturn(JoinPoint joinPoint, Object resp) {

    }

    /**
     * 目標方法非正常結束時打印
     *
     * @param throwable 異常信息,此參數是方法執行中拋出的異常信息,和@AfterThrowing注解中throwing屬性的值是一致的
     */
    @AfterThrowing(value = "point()", throwing = "throwable")
    public BaseResp afterThrowing(Throwable throwable) {
        BaseResp result=new BaseResp(ResultCodeEnum.R500);
        logger.error("【流量增益平台】【{}.{}】請求異常,req:{},",throwable);
        return result;

    }
}

 


免責聲明!

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



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