在使用切面前,首先保證項目配置啟動對@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; } }