什么是 Spring AOP
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 处。
浙公网安备 33010602011771号