我们知道,AOP是Spring Framework的两大特性之一,AOP通俗地讲就是可以实现对方法的增强,并且是以代码侵入性低的方式。其底层实现基于动态代理,如果代理对象没有实现某个接口,那么会用jdk代理,如果实现了某个接口,就用CGlib
AOP的一个很常见的使用场景就是日志
添加依赖代码org.springframework.boot spring-boot-starter-aop
实现AOP有多种方式,这里我们用最常用的一种,即基于注解的方式
定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
String operation() default "";
}
给需要增强的方法添加注解
@LogAnnotation(operation = "简单介绍")
public ResponseResult method(){
return ResponseResult.okResult();
}
写切面类
@Pointcut的属性来指定对哪些方法增强
这里我们用切点函数来表示对加了LogAnnotation注解的方法增强(除了这种方式,也可以写切点表达式来实现对方法的简单的批量增强)
@Pointcut("@annotation(com.cyz.annotation.LogAnnotation)")
public void pt(){
}
AOP支持五种通知方式,即
-
@Before:前置通知,在目标方法执行前执行
-
@AfterReturning: 返回后通知,在目标方法执行后执行,如果出现异常不会执行
-
@After:后置通知,在目标方法之后执行,无论是否出现异常都会执行
-
@AfterThrowing:异常通知,在目标方法抛出异常后执行
-
@Around:环绕通知,围绕着目标方法执行
这里我们采用环绕通知
@Around("pt()")
public Object log(ProceedingJoinPoint point) throws Throwable {
Object result =null;
long beginTime = System.currentTimeMillis();
//执行方法
try {
result = point.proceed();
}finally {
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
recordLog(point);
log.info("Response : {}",JSON.toJSONString(result));
log.info("excute time : {} ms",time);
log.info("=====================log end================================");
}
return result;
}
以上增强代码,主要记录了方法的执行时间,方法的返回值,以及记录了一些基本的日志信息(在封装的方法中我记录了url,http method等基本信息,通过ProceedingJoinPoint对象可以很容易被增强方法的相关信息)



