springboot中通過aop的形式獲取方法執行時間

前言

老大讓本人寫一個方法,獲取controller中的每個方法的執行時間,大於一定時間的抓出來,後期做優化。
網上找了一些方法,特此記錄一下。

注意:這裏需要各位同學對springboot有一定的瞭解。


話不多說,直接上代碼:

aspect類:

package com.fengye.aspect;

import com.fengye.common.enums.ResultEnum;
import com.fengye.exception.MethodRunningTimeException;
import lombok.extern.slf4j.Slf4j;
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.springframework.stereotype.Component;

/**
 * @Description Aop切面類
 * @Author ZF
 * @Time 2017/8/14 11:12
 */
@Aspect
@Slf4j
@Component
public class HttpAspect {

    /**
     * 切入點
     */
    @Pointcut("execution( * com.fengye.controller.*.*.*(..))")
    public void aopPointCut() {}

    /**
     * 統計方法耗時環繞通知
     * @param joinPoint
     */
    @Around("aopPointCut()")
    public Object timeAround(ProceedingJoinPoint joinPoint) {
        long startTime;
        long E_time;
        Object obj;
        try {
            // 獲取開始時間
            startTime = System.currentTimeMillis();
            // 獲取返回結果集
            obj = joinPoint.proceed(joinPoint.getArgs());
            // 獲取方法執行時間
            E_time = System.currentTimeMillis() - startTime;
        } catch (Throwable t) {
            // 當方法中報異常時,會拋出這裏的異常,
            throw new MethodRunningTimeException(ResultEnum.METHOD_RUNNING_TIME_ERROR, t);
        }
        String classAndMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        log.info("執行 " + classAndMethod + " 耗時爲:" + E_time + "ms");
        return obj;
    }
}

UserController類:

/**
     * SwaggerUI 相關Demo
     * 以api開頭的註解基本都是SwaggerUI的註解,可以多瞭解
     *
     * @param id 測試id  117390L
     * @return
     */
    @ApiOperation(value = "findUsersById()", notes = "根據id查詢用戶")
    @PostMapping(value = "/findUsersById")
    @ApiResponse(code = 1, message = "返回用戶實體")
    public Result findUsersById(@ApiParam(name = "id", value = "用戶Id") Long id) {
        Users users;
        try {
            System.out.println(keyValue);
            /**
             * log相關Demo
             */
            log.info("根據id爲{}的查找用戶", 117390);
            log.warn("根據id爲{}的查找用戶", 117390);
            log.error("根據id爲{}的查找用戶", 117390);

            users = usersService.findUsersById(117400L);

            /**
             * 異常處理相關Demo
             */
            int i = 1 / 0;  // 此處異常
        } catch (Exception e) {
            // 此處拋出自定義異常: UserException
            throw new UserException(ResultEnum.FIND_USER_BY_ID_ERROR, e);
        }
        return ResultUtils.success(users);
    }

但是這裏會有問題:
當方法正常執行時,沒有問題,可以成功獲取執行時間;
當方法內報異常時,這樣會直接拋出aspect中的異常,即:
throw new MethodRunningTimeException(ResultEnum.METHOD_RUNNING_TIME_ERROR, t);
即代碼中的從而覆蓋掉方法內部中你的自定義異常 。即:
throw new UserException(ResultEnum.FIND_USER_BY_ID_ERROR, e);
如果當你項目無論是否異常約定的返回格式都是是統一的,而且要通過返回的準確信息來定位異常的話,這種方法就不太可取。

所以我這裏還是使用最原始的方法來做:

package com.fengye.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @Description Aop切面類
 * @Author ZF
 * @Time 2017/8/14 11:12
 */
@Aspect
@Slf4j
@Component
public class HttpAspect {

    String methodName;      // 方法名
    long startTime;         // 開始時間

    /**
     * 切入點
     */
    @Pointcut("execution( * com.fengye.controller.*.*.*(..))")
    public void aopPointCut() {}

    /**
     * 統計方法耗時環繞通知
     * @param joinPoint
     */
    // @Around("aopPointCut()")
    // public Object timeAround(ProceedingJoinPoint joinPoint) {
    //     long startTime;
    //     long E_time;
    //     Object obj;
    //     try {
    //         // 獲取開始時間
    //         startTime = System.currentTimeMillis();
    //         // 獲取返回結果集
    //         obj = joinPoint.proceed(joinPoint.getArgs());
    //         // 獲取方法執行時間
    //         E_time = System.currentTimeMillis() - startTime;
    //     } catch (Throwable t) {
    //         throw new MethodRunningTimeException(ResultEnum.METHOD_RUNNING_TIME_ERROR, t);
    //     }
    //     String classAndMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
    //     log.info("執行 " + classAndMethod + " 耗時爲:" + E_time + "ms");
    //     return obj;
    // }

    @Before("aopPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        methodName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        startTime = System.currentTimeMillis();
    }

    @After("aopPointCut()")
    public void doAfter() {
        long E_time = System.currentTimeMillis() - startTime;
        log.info("執行 " + methodName + " 耗時爲:" + E_time + "ms");
    }

    @AfterReturning(returning = "object", pointcut = "aopPointCut()")
    public void doAfterReturning(Object object) {
        log.info("response={}", object.toString());
    }
}

相關注解的知識,推薦一個鏈接 http://blog.csdn.net/rainbow702/article/details/52185827

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