Skip to content

什么是AOP

什么是AOP#

以一个HTTP请求为例,客户端发送请求时会经过Controller(控制器),Service(服务)、DB(数据访问或操作)等模块,如果想要在这些模块中加入一些操作,例如数据验证、权限校验或者日志统计等等,该如何操作呢?

首先,我们可能会想到在Controller中加入参数校验或者权限校验逻辑,如果不通过,就直接返回错误,这样看起来没有什么问题,但是,如果有多个功能模块都需要进行校验,并且校验的逻辑几乎相同,那就意味着,需要在多个Controller中重复加入这段逻辑。

显然,这样做会导致公共逻辑与业务逻辑耦合,所以,我们需要一个方式,做到统一管理

image-20250115162906030

由上图的方式,我们可以看到,在Controller层的前后,都可以**“切一刀”**,用来统一处理公共逻辑,这样,就不会侵入Controller、Service等业务代码。

这样的方式,我们就叫做AOP(Aspect-Oriented Programming,面向切面编程),它是一种编程范式,它通过 分离关注点 来增强代码的模块化。AOP 允许开发者在不改变原有代码的前提下,在程序的特定位置添加行为,通常用于实现横切关注点(cross-cutting concerns),如日志记录、性能监控、安全检查、事务管理等

当然,在一些面向对象的后端系统中,AOP还有很多的概念,例如下面的这些:

切面(Aspect) 切面是用来定义横切关注点的模块。它包含了额外的行为和逻辑,可以在程序的不同部分被动态织入。

连接点(Join Point) 连接点是程序执行过程中可以插入切面的特定点。例如:方法调用、方法执行、属性访问等。

切入点(Pointcut) 切入点定义了在什么条件下插入切面逻辑。它通常通过表达式来匹配连接点。

通知(Advice) 通知是切面在连接点上执行的实际行为。通知可以在连接点的环绕执行。

  • 前置通知(Before Advice):在方法执行前执行。
  • 后置通知(After Advice):在方法执行后执行。
  • 环绕通知(Around Advice):在方法执行前后都执行,开发者可以完全控制方法的执行流程。

目标对象(Target Object) 目标对象是被切面增强的原始对象。

织入(Weaving) 织入是将切面应用到目标对象的过程,有以下几种方式:

  • 编译期织入:在编译阶段将切面代码织入目标类。
  • 加载期织入:在类加载时使用类加载器动态地将切面织入。
  • 运行期织入:在运行时使用代理模式将切面织入目标对象。

事实上,在Nest中,请求流程可以换一种角度来看:

Nest请求流程

中间的区域属于AOE切面部分,包含Middleware(中间件)、Guard(守卫)、Interceptor(拦截器)、Pipe(管道)和Filter(过滤器)。他们都是AOP思想的具体实现