AOP(面向切面编程)是 Spring 两大核心之一,它是一种编程思想,是对 OOP 的一种补充。它通过横向抽取共性功能(如日志、事务),解决代码重复和耦合问题,提升代码复用性和可维护性。它的底层是通过动态代理实现的。
例子:记录 Controller 请求日志
如何给所有的 Controller 加日志?一个个加太麻烦、不好维护,且容易改错而导致出问题。
可以用 AOP 做统一的控制层日志记录。以 demo-log-aop 为例(为易于理解,省略了一些细节):
com.xkcoding.log.aop.controller包下有一个 Controller:
/*** 测试 Controller*/
@Slf4j
@RestController
public class TestController {/*** 测试方法** @param who 测试参数*/@GetMapping("/test")public Dict test(String who) {return Dict.create().set(who);}
}
可以如下使用 AOP 切面记录请求日志:
/*** 使用 AOP 切面记录请求日志信息*/
@Aspect
@Component
@Slf4j
public class AopLog {/*** 切入点*/@Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")public void log() {}/*** 环绕操作** @param point 切入点* @return 原方法返回值* @throws Throwable 异常信息*/@Around("log()")public Object aroundLog(ProceedingJoinPoint point) throws Throwable {// 调用方法Object result = point.proceed();// 构建日志对象final Log l = buildLog(point);// 打印日志log.info("Request Log Info : {}", JSONUtil.toJsonStr(l));// 返回原方法返回值return result;}/*** 构建日志对象*/public Log buildLog(ProceedingJoinPoint point){// ...}
}
其中execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))是“切入点表达式”,可匹配“com.xkcoding.log.aop.controller 包下的所有以 Controller 结尾的类的所有 public 方法”——包括上面 TestController 中的 test 方法。
aroundLog 方法中写了具体的日志逻辑,在上面加@Around("log()")注解使其和log()绑定。
调用 TestController.test 之前,会发现切入点表达式匹配该方法,所以执行和该 Pointcut 绑定的 aroundLog 方法,aroundLog 中的point.proceed()完成了 TestController.test 的调用,调用 TestController.test 后,打印了相关的日志信息。
概念
-
AOP:面向方面(切面)的程序设计(Aspect-Oriented Programming)。
-
JoinPoint(连接点):在系统运行之前,AOP 的功能模块都需要织入到具体的功能模块中。要进行这种织入过程,我们需要知道在系统的哪些执行点上进行织入过程,这些将要在其之上进行织入操作的系统执行点就称之为 JoinPoint,最常见的 JoinPoint 就是方法调用。
-
Pointcut(切点):用于指定一组 JoinPoint,代表要在这一组 JoinPoint 中织入我们的逻辑,它定义了相应 Advice 将要发生的地方。通常使用正则表达式来表示。对于做日志记录,Pointcut 就是表示“所有要加入日志记录的接口”的一个“表达式”。例如:“execution(* com.open.demo.service...(..))”。
-
Advice(通知/增强):Advice 定义了将会织入到 JoinPoint 的具体逻辑,通过 @Before、@After、@Around 来区别在 JointPoint 之前、之后还是环绕执行的代码。
-
Aspect(切面):Aspect 是对系统中的横切关注点逻辑进行模块化封装的 AOP 概念实体。类似于 Java 中的类声明,在 Aspect 中可以包含多个 Pointcut 以及相关的 Advice 定义。
-
Weaving(织入):织入指的是将 Advice 连接到 Pointcut 指定的 JoinPoint 处的过程,也称为:将 Advice 织入到 Pointcut 指定的 JoinPoint 处。
参考:Spring AOP:基本概念