Spring AOP 核心概念:切面、通知、切点、织入

提到 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种通知类型

通知的核心区别,在于「执行时机不同」,结合实战场景理解,不用死记硬背:

    1. 前置通知(@Before):切点方法执行「之前」执行,比如接口执行前的权限校验、参数校验;
    1. 后置通知(@After):切点方法执行「之后」执行(无论是否抛出异常),比如接口执行后的日志记录、资源释放;
    1. 返回通知(@AfterReturning):切点方法「正常执行完成后」执行,比如获取接口返回结果,做后续处理;
    1. 异常通知(@AfterThrowing):切点方法「抛出异常后」执行,比如异常捕获、日志记录、报警;
    1. 环绕通知(@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 核心逻辑,最后执行后置通知(日志记录)------这个"动态代理+增强逻辑融入"的过程,就是织入。

四大概念的关系

用一句话总结四大概念的协同关系:通过「织入」过程,将「切面」(包含「切点」和「通知」)动态应用到目标对象,实现不修改核心代码的增强

    1. 切点:定位"要增强的方法"(在哪里加);
    1. 通知:定义"增强的逻辑"(加什么);
    1. 切面:绑定切点和通知(把"在哪里加"和"加什么"整合);
    1. 织入:将切面的增强逻辑,动态融入目标方法(怎么加,何时加)。

注意事项

混淆切点和通知

❌ 错误认知:以为切点就是增强逻辑;

✅ 正确区分:切点只负责"定位位置",通知负责"执行逻辑",两者必须绑定在切面中,才能实现增强。

忘记给切面加 @Component 注解

❌ 错误做法:只加 @Aspect 标记切面,忘记加 @Component;

✅ 正确做法:@Aspect 只是标记此类是切面,必须加 @Component 交给 Spring 管理,Spring 才能扫描到切面,完成织入。

文末小结

其实 Spring AOP 四大核心概念,本质就是"分工协作":切点找位置、通知做事情、切面整合成模块、织入落地执行,最终实现"无侵入式增强"。

同学们在学习时,不用死记硬背术语,结合「保安站岗」的类比,再对照实战案例,就能快速理解;后续学习 AOP 实战(比如全局日志、权限校验),再回头看这四个概念,会发现一切都很简单。

如果你在学习 AOP 时遇到过困惑,或者有更好的理解方法,欢迎在评论区留言交流,一起避坑、一起进步!

别忘了点赞+在看+收藏三连,关注我,解锁更多 Spring 实战干货,下期再见❤️

相关推荐
Bernard02151 小时前
给普通人的 AI 黑话翻译手册:一文看懂 LLM、RAG、Agent 到底是什么
前端·后端
泰式大师1 小时前
# 为什么我认为 Hermes 需要说明 self-evolution 的设计来源
后端
胖纳特1 小时前
Seafile 文件预览增强方案:集成 BaseMetas Fileview 突破格式限制
前端·后端
fliter1 小时前
Rust这四个问题,从新手到专家都在被折磨
后端
山峰哥1 小时前
SQL查询优化实战:从Explain分析到索引策略的深度解析
数据库·oracle
lxh01132 小时前
电话号码的字母组合
java·javascript·算法
CodeSheep2 小时前
同事偷偷给我介绍私活,说1万报酬全给我,结果甲方私下告诉我说,同事在当中白拿了2万,我觉得被耍了,媳妇却让我要知足,说我一点不亏
前端·后端·程序员
爱学习的小可爱卢2 小时前
算法—Java Map 核心方法与实战场景指南
java·开发语言·算法
X1A0RAN2 小时前
容器化部署elasticsearch教程+python操作es数据库示例
数据库·python·elasticsearch