SpringBoot中AOP的使用

導入依賴

在pom文件中加入如下依賴

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

LogAOP

創建一個日誌切面,用來記錄方法執行耗時

@Aspect
@Order(1)
@Configuration
public class LogAop {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    // 切點
    private final static String POINTCUT_LOG_CONTROLLER = "execution (* com.frog.mybatisplus.controller.*.*(..))";
    private final static String POINTCUT_LOG_SERVICE = "execution (* com.frog.mybatisplus.service.impl.*.*(..))";
    private final static String POINTCUT_LOG = POINTCUT_LOG_CONTROLLER + " || " + POINTCUT_LOG_SERVICE;

    // 環繞通知
    @Around(POINTCUT_LOG)
    public Object logAround(ProceedingJoinPoint joinPoint) {
        // 獲取切點參數
        Object[] args = joinPoint.getArgs();
        // 獲取方法全限定名
        String methodName = joinPoint.getSignature().getDeclaringTypeName();
        // 打印執行前日誌
        printBeforeLog(methodName, args);
        // 執行時間起
        long start = System.currentTimeMillis();
        try {
            // 執行方法
            Object proceed = joinPoint.proceed();
            // 執行時間止
            long end = System.currentTimeMillis();
            // 打印執行後日志
            printAfterLog(methodName, args, proceed, end - start);
			return proceed;

        } catch (Throwable e) {
            // 處理異常
            printErrorLog(methodName, args, e);
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else {
                throw new RuntimeException(e);
            }
        }
    }

    private void printErrorLog(String methodName, Object[] args, Throwable e) {
        if (logger.isInfoEnabled()) {
            logger.info("[{}] 方法執行異常,參數[{}],異常信息[{}]",
                    methodName,
                    argsToParamStr(args),
                    e);
        }
    }

    private void printAfterLog(String methodName, Object[] args, Object proceed, long l) {
        if (proceed == null) {
            proceed = "null";
        }
        if (logger.isInfoEnabled()) {
            logger.info("[{}] 方法執行成功,參數[{}],執行時間[{}ms],返回值[{}]",
                    methodName,
                    argsToParamStr(args),
                    l,
                    proceed);
        }
    }

    private void printBeforeLog(String methodName, Object[] args) {
        if (logger.isInfoEnabled()) {
            logger.info("[{}] 方法請求成功,參數[{}]", methodName, argsToParamStr(args));
        }
    }

    private String argsToParamStr(Object[] args) {
        return Stream.of(args)
                .map(o -> {
                    if (o == null) {
                        return "null";
                    }
                    if (o.getClass().isPrimitive()) {
                        // 基本類型輸出值
                        return o.toString();
                    } else {
                        // 不是基本類型
                        if (o.toString().length() > 100) {
                            return o.getClass().getName();
                        } else {
                            return o.toString();
                        }
                    }
                })
                .collect(Collectors.joining(", ", "{", "}"));
    }
}

@Aspect註解表示這是一個切面
@Order(1)執行順序,數字越小越先進入切面
@Around環繞通知,相當於把執行方法包裹起來,也可以使用@Before+@AfterReturning+@AfterThrowing達到相同效果。

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