切面
springboot中使用@Aspect注解标注的类,通俗地理解就是一个实现了要增强方法的增强操作的实现类,类中定义了增强方法执行前后等情况要进行的操作。
连接点
表示AOP增强方法的执行,即被AOP切面类增强的方法。
通知
表示连接点执行前后或遇到异常等情况要执行的操作,用不同的注解来表示,有如下5中通知类型:
| 注解 | 描述 |
| @Before | 前置通知, 在方法执行之前执行 |
| @After | 后置通知, 在方法执行之后执行 |
| @AfterReturn | 返回通知, 在方法返回结果之后执行|
| @AfterThrowing | 异常通知, 在方法抛出异常之后 |
| @Around | 环绕通知,围绕方法的执行 |
切入点
匹配连接点的断言,表示要在什么样的方法进行AOP增强,形式如下:
execution(修饰符 返回值类型 方法名(参数)异常)
通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行。
AOP常用来记录一些方法的执行日志,下面以记录控制类的执行日志为例子来说明Springboot如何使用AOP。
org.springframework.boot spring-boot-starter-aop 2.5.0
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);// 获取ipHttpServletRequest 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================");}
}
执行结果如下: