提到 Spring,就绕不开 AOP;提到 AOP,很多同学都会被「切面、通知、切点、织入」这四个核心概念搞懵,觉得抽象难理解,甚至越学越乱。
其实 AOP 一点都不复杂,它的核心就是「在不修改原有代码的前提下,对代码进行增强」------比如统一日志打印、接口权限校验、异常统一处理,这些都是 AOP 的典型应用。
什么是 Spring AOP?
AOP 全称 Aspect Oriented Programming,即「面向切面编程」,是 Spring 两大核心特性之一(另一个是 IOC)。
通俗来讲,AOP 就像「给代码"戴帽子"」:原有业务代码(比如用户登录、订单支付)是核心,我们不需要修改这些核心代码,只需要在代码执行的某个节点(比如执行前、执行后),动态添加一些通用功能(比如日志、权限校验)------这些通用功能就像"帽子",戴在核心代码上,不影响核心逻辑,还能实现功能复用。
举个最直观的例子:一个电商系统的「订单支付接口」,核心逻辑是"扣减库存、扣减余额";而我们需要在支付前校验用户权限,支付后打印操作日志、记录支付记录。这些"权限校验、日志打印"就是 AOP 要做的事,无需修改支付接口的核心代码,就能完成增强。
而「切面、通知、切点、织入」,就是实现这种"动态增强"的四大核心组件,各司其职、协同工作。
四大概念
我们用「学校保安站岗」来类比四大概念,帮你快速理解:
学校的「教学活动」(比如上课、考试)是核心业务;保安的「站岗、登记、巡逻」是通用功能,不影响教学,但能保障校园安全------保安的工作,就相当于 AOP 的增强逻辑;而保安如何安排站岗(什么时候站、在哪个门口站、怎么站),就对应 AOP 四大概念。
一、切点(Pointcut):"在哪里增强"------精准定位增强位置
切点就是「明确增强的位置」,相当于保安的「站岗地点」(比如学校正门、侧门),只有经过这些地点的人(对应代码中的方法),才会被增强(被保安登记)。
在 Spring AOP 中,切点的核心作用是:通过表达式,精准匹配需要被增强的方法,过滤掉不需要增强的方法,避免"无差别增强"。
示例
比如我们要给「所有订单相关的接口」添加日志增强,那么"所有订单相关的方法"就是切点;再比如,只给「支付接口(payOrder)」添加权限校验,那么"payOrder 方法"就是切点。
Spring AOP 常用切点表达式:
go
// 1. 匹配指定包下的所有方法(最常用)
execution(* com.example.demo.service.*.*(..))
// 解读:com.example.demo.service 包下的所有类、所有方法,无论返回值、参数是什么
// 2. 匹配指定类的所有方法
execution(* com.example.demo.service.OrderService.*(..))
// 3. 匹配指定方法(精准匹配)
execution(* com.example.demo.service.OrderService.payOrder(..))
关键点:切点只负责「定位位置」,不负责「做什么增强」。
二、通知(Advice):"增强做什么"------定义增强逻辑
通知就是「增强的具体逻辑」,相当于保安的「具体工作内容」(比如登记身份、测量体温),明确在切点位置,要做什么事。
在 Spring AOP 中,通知的核心作用是:定义在切点方法执行的某个时机,执行什么样的增强逻辑,是 AOP 增强的"具体实现"。
Spring AOP 5种通知类型
通知的核心区别,在于「执行时机不同」,结合实战场景理解,不用死记硬背:
-
- 前置通知(@Before):切点方法执行「之前」执行,比如接口执行前的权限校验、参数校验;
-
- 后置通知(@After):切点方法执行「之后」执行(无论是否抛出异常),比如接口执行后的日志记录、资源释放;
-
- 返回通知(@AfterReturning):切点方法「正常执行完成后」执行,比如获取接口返回结果,做后续处理;
-
- 异常通知(@AfterThrowing):切点方法「抛出异常后」执行,比如异常捕获、日志记录、报警;
-
- 环绕通知(@Around):包裹切点方法,可在方法执行前、执行后、异常时做处理,功能最强大(实战中最常用)。
示例
比如给支付接口(payOrder)添加增强:
-
• 前置通知:校验用户是否登录、是否有支付权限;
-
• 返回通知:支付成功后,记录支付金额、订单号,同步到消息队列;
-
• 异常通知:支付失败(比如余额不足),捕获异常,记录错误日志,提示用户。
三、切面(Aspect):"把增强和位置绑定"------整合切点和通知
切面就是「把切点和通知绑定在一起」,相当于「保安的工作安排」:明确"在哪个门口(切点),做什么工作(通知)",是 AOP 的核心组件,将分散的增强逻辑和定位规则整合起来。
在 Spring AOP 中,切面的核心作用是:封装切点和通知,形成一个独立的模块,实现增强逻辑的复用(比如一个切面可以绑定多个切点和通知,实现全局日志增强)。
简单说:切面 = 切点 + 通知,没有切面,切点和通知就是孤立的,无法完成增强。
示例
我们创建一个「日志切面」,绑定切点和通知,实现全局接口日志增强:
go
// 用 @Aspect 注解标记此类为切面
@Aspect
@Component // 交给 Spring 管理
public class LogAspect {
// 1. 定义切点:匹配所有 service 包下的方法
@Pointcut("execution(* com.example.demo.service.*.*(..))")
public void logPointcut() {} // 切点方法,无实际逻辑,仅用于标记
// 2. 定义通知:前置通知,在切点方法执行前执行
@Before("logPointcut()")
public void beforeLog(JoinPoint joinPoint) {
// 增强逻辑:打印请求方法名、参数
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("前置通知:执行方法:" + methodName + ",参数:" + Arrays.toString(args));
}
// 3. 定义通知:后置通知,在切点方法执行后执行
@After("logPointcut()")
public void afterLog() {
System.out.println("后置通知:方法执行完成");
}
}
解读:这个 LogAspect 就是一个切面,logPointcut() 是切点(定位所有 service 方法),beforeLog 和 afterLog 是通知(定义日志增强逻辑),两者通过注解绑定,实现全局日志增强。
四、织入(Weaving):"何时增强"------将切面应用到目标对象的过程
织入就是「把切面的增强逻辑,动态添加到目标对象(核心业务代码)的过程」,相当于「保安到岗执行工作」的过程------把"站岗安排(切面)"落地到实际场景中。
在 Spring AOP 中,织入的核心作用是:将切面的增强逻辑,在指定时机(编译期、类加载期、运行期)融入到目标对象的方法中,完成动态增强,且不修改目标对象的原有代码。
Spring AOP 织入时机
Spring AOP 采用「运行期织入」(最灵活,也是实战中唯一使用的方式):
-
• 编译期织入:在代码编译时,将增强逻辑融入目标类(需要特殊编译器,不常用);
-
• 类加载期织入:在目标类加载到 JVM 时,将增强逻辑融入(需要自定义类加载器,较少用);
-
• 运行期织入:在程序运行时,通过 Spring 动态代理(JDK 动态代理、CGLIB 代理),动态生成目标对象的代理对象,将切面增强逻辑融入代理对象中------无需修改原有代码,灵活高效,Spring 默认采用这种方式。
示例
当我们启动 Spring 项目时,Spring 会自动扫描 @Aspect 标记的切面,通过动态代理,将切面中的增强逻辑(通知),织入到切点匹配的方法中。比如我们调用 OrderService 的 payOrder 方法时,Spring 会生成 OrderService 的代理对象,先执行前置通知(权限校验),再执行 payOrder 核心逻辑,最后执行后置通知(日志记录)------这个"动态代理+增强逻辑融入"的过程,就是织入。
四大概念的关系
用一句话总结四大概念的协同关系:通过「织入」过程,将「切面」(包含「切点」和「通知」)动态应用到目标对象,实现不修改核心代码的增强。
-
- 切点:定位"要增强的方法"(在哪里加);
-
- 通知:定义"增强的逻辑"(加什么);
-
- 切面:绑定切点和通知(把"在哪里加"和"加什么"整合);
-
- 织入:将切面的增强逻辑,动态融入目标方法(怎么加,何时加)。
注意事项
混淆切点和通知
❌ 错误认知:以为切点就是增强逻辑;
✅ 正确区分:切点只负责"定位位置",通知负责"执行逻辑",两者必须绑定在切面中,才能实现增强。
忘记给切面加 @Component 注解
❌ 错误做法:只加 @Aspect 标记切面,忘记加 @Component;
✅ 正确做法:@Aspect 只是标记此类是切面,必须加 @Component 交给 Spring 管理,Spring 才能扫描到切面,完成织入。
文末小结
其实 Spring AOP 四大核心概念,本质就是"分工协作":切点找位置、通知做事情、切面整合成模块、织入落地执行,最终实现"无侵入式增强"。
同学们在学习时,不用死记硬背术语,结合「保安站岗」的类比,再对照实战案例,就能快速理解;后续学习 AOP 实战(比如全局日志、权限校验),再回头看这四个概念,会发现一切都很简单。
如果你在学习 AOP 时遇到过困惑,或者有更好的理解方法,欢迎在评论区留言交流,一起避坑、一起进步!
别忘了点赞+在看+收藏三连,关注我,解锁更多 Spring 实战干货,下期再见❤️