Spring知识梳理(4)
📅 2026/7/18 16:24:00
👁️ 阅读次数
📝 编程学习
Spring知识梳理(4)
作者:没有四次元口袋的蓝胖
日期:2026-07-16
标签:Java, Spring, AOP, 面向切面编程
一、AOP 是什么
AOP(Aspect-Oriented Programming,面向切面编程)是对 OOP 的补充。
- OOP:纵向继承,解决类与类之间的复用(封装、继承、多态)
- AOP:横向抽取,解决跨多个类的公共行为复用(日志、事务、权限、性能监控)
传统 OOP 的问题: UserService OrderService ProductService ↓ ↓ ↓ 日志代码 日志代码 日志代码 ← 重复! 事务代码 事务代码 事务代码 ← 重复! 权限代码 权限代码 权限代码 ← 重复! AOP 的解决方式: UserService OrderService ProductService ↓ ↓ ↓ ┌─────────┐ │ AOP 切面 │ ← 统一抽取,一处维护 └─────────┘一句话总结:AOP 把散落在各处的公共逻辑抽到一个地方统一管理,不侵入业务代码。
二、核心术语(7 个必须分清)
| 术语 | 英文 | 含义 | 例子 |
|---|---|---|---|
| 切面 | Aspect | 横切关注点的模块化 | 日志切面、事务切面 |
| 连接点 | JoinPoint | 程序执行的某个点(方法调用、异常抛出) | 每个方法都是一个连接点 |
| 切入点 | Pointcut | 你选择的哪些连接点要被增强 | execution(* service.*.*(..)) |
| 通知(增强) | Advice | 切入后做什么 | 打日志、开事务 |
| 目标对象 | Target | 被代理的原始对象 | UserService 实例 |
| 代理对象 | Proxy | AOP 生成的增强后的对象 | 包含日志逻辑的 UserService |
| 织入 | Weaving | 把切面逻辑应用到目标对象的过程 | Spring 在运行时通过代理完成 |
面试口诀:切面 = 切入点 + 通知。切入点决定"在哪里切入",通知决定"切入后做什么"。
连接点 vs 切入点(最容易混淆)
- 连接点:程序中所有可以被拦截的点(所有方法),是客观存在的
- 切入点:你实际选中的那些连接点,是主观选择的
所有方法 = 连接点(全集) 你选中的方法 = 切入点(子集)三、五种通知类型
| 通知 | 注解 | 执行时机 | 用途 |
|---|---|---|---|
| 前置通知 | @Before | 目标方法执行前 | 参数校验、权限检查 |
| 后置通知 | @AfterReturning | 目标方法正常返回后 | 日志记录 |
| 环绕通知 | @Around | 包裹目标方法执行 | 事务管理、性能监控 |
| 异常通知 | @AfterThrowing | 目标方法抛出异常后 | 异常处理、告警 |
| 最终通知 | @After | 目标方法执行后(无论是否异常) | 资源清理(类似 finally) |
执行顺序
正常执行流程: @Around 前半 → @Before → 目标方法 → @Around 后半 → @AfterReturning → @After 异常执行流程: @Around 前半 → @Before → 目标方法(抛异常)→ @AfterThrowing → @After注意:
@After类似于finally,无论正常返回还是异常都会执行。@AfterReturning只在正常返回时执行。
@Around 为什么最强大?
@Around("pointcut()")publicObjectaround(ProceedingJoinPointpjp)throwsThrowable{// 前置逻辑longstart=System.currentTimeMillis();// 可以决定是否执行目标方法(调不调 proceed())Objectresult=pjp.proceed();// 不调用则目标方法不执行// 后置逻辑longcost=System.currentTimeMillis()-start;System.out.println("耗时: "+cost+"ms");// 甚至可以修改返回值returnresult;}@Around能做的事:
- ✅ 控制目标方法是否执行(不调
proceed()就行) - ✅ 修改入参
- ✅ 修改返回值
- ✅ 捕获异常不让它传播
其他四种通知做不到这些。
四、Spring AOP 完整执行流程
客户端调用 proxy.method() ↓ 代理对象拦截方法调用 ↓ 根据 Pointcut 匹配:这个方法需要被增强吗? ├── 是 → 按通知类型执行增强逻辑 │ ├── @Before │ ├── 目标方法 │ ├── @AfterReturning / @AfterThrowing │ └── @After └── 否 → 直接调用目标对象的方法五、思维导图速览
Spring AOP ├── 核心思想 │ ├── 横向抽取公共逻辑(日志、事务、权限) │ ├── 不修改源代码,运行时织入 │ └── 底层 = 动态代理(下篇详解) │ ├── 7 个核心术语 │ ├── Aspect(切面)= Pointcut + Advice │ ├── JoinPoint(连接点)= 所有可拦截的点 │ ├── Pointcut(切入点)= 你选中的连接点 │ ├── Advice(通知)= 切入后做什么 │ ├── Target / Proxy / Weaving │ └── 关键区分:连接点(全集)vs 切入点(子集) │ ├── 五种通知 │ ├── @Before(前置) │ ├── @AfterReturning(后置) │ ├── @Around(环绕)← 最强大,控制执行流 │ ├── @AfterThrowing(异常) │ └── @After(最终,类似 finally) │ └── 执行顺序 ├── 正常:Around前 → Before → 方法 → Around后 → AfterReturning → After └── 异常:Around前 → Before → 方法抛异常 → AfterThrowing → After六、写在最后
面试回答模板
“AOP 是面向切面编程,把散落在各处的公共逻辑统一抽取管理。核心概念有 7 个,最重要的是切面 = 切入点 + 通知。切入点决定在哪里切入,通知决定切入后做什么。通知有五种,@Around 最强大,可以控制目标方法是否执行、修改入参和返回值。AOP 底层通过动态代理实现,运行时生成代理对象。”
学习建议
- 7 个术语:重点区分"连接点 vs 切入点",面试常考
- 五种通知:记住执行顺序,理解 @Around 为什么最强
编程学习
技术分享
实战经验