AOP启动配置
在使用切面前,首先保证项目配置启动对@AspectJ注解的支持及监听类,在Spring的配置文件中,添加如下配置即可:
<!-- 启动对@AspectJ注解的支持 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
AOP代码示例(注解方式实现)
Aop示例之注解方式实现日志打印
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;
}
}