1. AOP术语说明
-
切面
springboot中使用@Aspect注解标注的类,通俗地理解就是一个实现了要增强方法的增强操作的实现类,类中定义了增强方法执行前后等情况要进行的操作。 -
连接点
表示AOP增强方法的执行,即被AOP切面类增强的方法。 -
通知
表示连接点执行前后或遇到异常等情况要执行的操作,用不同的注解来表示,有如下5中通知类型:
| 注解 | 描述 |
| @Before | 前置通知, 在方法执行之前执行 |
| @After | 后置通知, 在方法执行之后执行 |
| @AfterReturn | 返回通知, 在方法返回结果之后执行|
| @AfterThrowing | 异常通知, 在方法抛出异常之后 |
| @Around | 环绕通知,围绕方法的执行 | -
切入点
匹配连接点的断言,表示要在什么样的方法进行AOP增强,形式如下:
execution(修饰符 返回值类型 方法名(参数)异常)
通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行。
2. Springboot使用AOP
AOP常用来记录一些方法的执行日志,下面以记录控制类的执行日志为例子来说明Springboot如何使用AOP。
- 引入AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.5.0</version>
</dependency>
- 定义AOP注解
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface LogAnnotation {
String module() default "";
String operator() default "";
}
- 定义切面类
@Component
@Aspect
@Slf4j
public class LogAspect {
// 定义切点,表示被该注解注释的方法要被增强
@Pointcut("@annotation(com.tplink.blog.common.aop.LogAnnotation)")
public void pt() {}
@Around("pt()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long start = System.currentTimeMillis();
// 执行原来的方法
Object obj = point.proceed();
long end = System.currentTimeMillis();
// 保存日志
recordLog(point, end - start);
return obj;
}
// 记录日志
private void recordLog(ProceedingJoinPoint point, long time) {
// 获取署名信息对象
MethodSignature signature = (MethodSignature)point.getSignature();
// 通过反射获取Method对象
Method method = signature.getMethod();
// 获取方法上的注解对象
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
log.info("============================log start==========================");
log.info("module:{}", annotation.module());
log.info("operator:{}", annotation.operator());
// 获取请求方法名
String className = point.getTarget().getClass().getName();
String name = signature.getName();
log.info("request method:{}",className + "." + name + "()");
// 请求参数
Object[] args = point.getArgs();
String params = JSON.toJSONString(args[0]);
log.info("params:{}", params);
// 获取ip
HttpServletRequest request = HttpContextUtils.getServletRequest();
log.info("ip:{}", IpUtils.getIpAddr(request));
log.info("执行时间:{}ms", time);
log.info("============================log stop==========================");
}
}
- 定义控制类进行测试
@RestController
@RequestMapping("test")
public class TestController {
private Logger logger = LoggerFactory.getLogger(TestController.class);
@GetMapping("logAOP")
@LogAnnotation(module = "AOP测试", operator = "进行日志AOP")
public void testAOP(@RequestParam String param1) {
logger.info("===============进行日志AOP================");
}
}
执行结果如下: