博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。
② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。
③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。
进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。
群公告里还有全网大赛约稿汇总/博客提效工具集/CSDN自动化运营脚本 有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。
文章目录
- [Spring Boot AOP(一) 入门与核心概念](#Spring Boot AOP(一) 入门与核心概念)
-
- [1. AOP 基础概念](#1. AOP 基础概念)
- [2. 连接点与切入点表达式](#2. 连接点与切入点表达式)
-
- [2.1 JoinPoint 常用方法](#2.1 JoinPoint 常用方法)
- [2.2 切入点表达式常用类型](#2.2 切入点表达式常用类型)
- [2.3 切入点示意图](#2.3 切入点示意图)
- [3. Spring AOP 通知类型](#3. Spring AOP 通知类型)
- [4. 简单切面示例](#4. 简单切面示例)
- [5. 方法调用流程示意](#5. 方法调用流程示意)
- [6. 环绕通知深入解析](#6. 环绕通知深入解析)
- [7. AOP 与 Bean 生命周期交互](#7. AOP 与 Bean 生命周期交互)
- [8. 实战案例:日志 + 性能切面](#8. 实战案例:日志 + 性能切面)
- [9. 本文小结](#9. 本文小结)
- 结束语

Spring Boot AOP(一) 入门与核心概念
1. AOP 基础概念
AOP(Aspect-Oriented Programming,面向切面编程)是一种用于处理 横切关注点 (Cross-Cutting Concerns)的编程技术。在企业级项目中,日志记录、性能监控、事务管理、权限校验等通常会重复出现在多个模块,如果将这些逻辑直接写入业务方法,会导致代码耦合高、难维护。AOP 通过 切面(Aspect) 将这些横切逻辑模块化,从而解耦业务逻辑。
核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| 切面 Aspect | 横切关注点模块化封装 | 日志切面、事务切面 |
| 通知 Advice | 切面中具体执行操作 | @Before、@After、@Around |
| 连接点 JoinPoint | 可以被切面切入的位置 | 方法调用、异常抛出 |
| 切入点 Pointcut | 匹配连接点的表达式 | execution(* com.example.service....(...)) |
| 织入 Weaving | 将切面应用到目标对象的过程 | Spring AOP 在运行时生成代理 |
Spring AOP 默认使用 运行时动态代理,只对 Spring 管理的 Bean 生效,无法处理普通对象的直接方法调用。
2. 连接点与切入点表达式
2.1 JoinPoint 常用方法
java
@Around("execution(* com.example.service..*.*(..))")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("目标对象: " + pjp.getTarget());
System.out.println("方法签名: " + pjp.getSignature());
System.out.println("方法参数: " + Arrays.toString(pjp.getArgs()));
return pjp.proceed();
}
| 方法 | 说明 |
|---|---|
| getTarget() | 目标对象 |
| getThis() | 当前代理对象 |
| getArgs() | 方法参数 |
| getSignature() | 方法签名 |
| proceed() | 执行目标方法(环绕通知专用) |
2.2 切入点表达式常用类型
| 表达式 | 含义 | 示例 |
|---|---|---|
| execution() | 匹配方法执行 | execution(* com.example.service....(...)) |
| within() | 匹配类或包 | within(com.example.service...*) |
| this() | 匹配代理对象类型 | this(com.example.service.MyService) |
| target() | 匹配目标对象类型 | target(com.example.service.MyService) |
| args() | 匹配参数类型 | args(String, ...) |
2.3 切入点示意图
匹配 不匹配 Service 层方法 匹配切入点? 执行切面通知 直接执行目标方法
3. Spring AOP 通知类型
| 类型 | 执行时机 | 注解 | 适用场景 |
|---|---|---|---|
| 前置通知 | 方法执行前 | @Before | 权限校验、日志记录 |
| 后置通知 | 方法执行后 | @After | 日志记录、资源清理 |
| 返回通知 | 方法成功返回后 | @AfterReturning | 日志记录、返回值处理 |
| 异常通知 | 方法抛出异常后 | @AfterThrowing | 异常记录、告警 |
| 环绕通知 | 方法执行前后 | @Around | 性能统计、异常统一处理 |
通知执行顺序示意
4. 简单切面示例
java
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service..*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("前置通知: 调用方法 " + joinPoint.getSignature().getName());
}
@AfterReturning(pointcut = "execution(* com.example.service..*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("返回通知: 方法返回值 " + result);
}
@Around("execution(* com.example.service..*.*(..))")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("环绕通知: 方法执行前");
Object result = pjp.proceed();
System.out.println("环绕通知: 方法执行后, 耗时 " + (System.currentTimeMillis() - start) + "ms");
return result;
}
}
5. 方法调用流程示意
Client Proxy Target 调用方法 执行 @Before 调用目标方法 返回结果 执行 @AfterReturning 或 @AfterThrowing 返回最终结果 Client Proxy Target
6. 环绕通知深入解析
环绕通知 (@Around) 可以完全控制目标方法的执行:
- 可以修改参数
- 可以捕获异常
- 可以修改返回值
- 可以决定是否执行目标方法
java
@Around("execution(* com.example.service..*.*(..))")
public Object secureAround(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
// 修改参数
args[0] = "modified";
try {
Object result = pjp.proceed(args);
return result;
} catch (Throwable ex) {
System.out.println("捕获异常: " + ex.getMessage());
throw ex;
}
}
流程图:环绕通知控制流程
7. AOP 与 Bean 生命周期交互
Spring AOP 使用 BeanPostProcessor 在 Bean 初始化后生成代理:
是 否 BeanDefinition 注册 Bean 实例化 依赖注入 postProcessBeforeInitialization 初始化方法 postProcessAfterInitialization 需要代理? 创建代理对象 直接返回 Bean 代理对象注入到容器
核心类:
AnnotationAwareAspectJAutoProxyCreatorProxyFactory/EnhancerAdvisor/Advice/Pointcut
8. 实战案例:日志 + 性能切面
java
@Aspect
@Component
public class PerformanceAspect {
@Around("execution(* com.example.service..*.*(..))")
public Object measureTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature() + " 耗时: " + duration + "ms");
return result;
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("调用方法: " + joinPoint.getSignature().getName());
}
@AfterReturning(pointcut = "execution(* com.example.service..*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("方法返回值: " + result);
}
}
多切面调用顺序示意
9. 本文小结
- AOP 是处理横切关注点的强大机制
- 切面 + 通知 + 切入点构成核心
- 环绕通知最灵活,可控制方法执行前后
- 多切面、Bean 生命周期、通知组合都需要清楚理解
- Mermaid 图帮助理解调用顺序和执行流程
结束语

👨💻 关于我
持续学习 | 追求真我
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
感谢订阅专栏 三连文章

掘金点击访问Qiuner CSDN点击访问Qiuner GitHub点击访问Qiuner Gitee点击访问Qiuner
| 专栏 | 简介 |
|---|---|
| 📊 一图读懂系列 | 图文并茂,轻松理解复杂概念 |
| 📝 一文读懂系列 | 深入浅出,全面解析技术要点 |
| 🌟持续更新 | 保持学习,不断进步 |
| 🎯 人生经验 | 经验分享,共同成长 |
你好,我是Qiuner. 为帮助别人少走弯路而写博客
如果本篇文章帮到了你 不妨点个赞 吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍
如果你遇到了问题,自己没法解决,可以去我掘金评论区问。CSDN评论区和私信消息看不完 掘金消息少一点.
| 上一篇推荐 | 链接 |
|---|---|
| Java程序员快又扎实的学习路线 | 点击该处自动跳转查看哦 |
| 一文读懂 AI | 点击该处自动跳转查看哦 |
| 一文读懂 服务器 | 点击该处自动跳转查看哦 |
| 2024年创作回顾 | 点击该处自动跳转查看哦 |
| 一文读懂 ESLint配置 | 点击该处自动跳转查看哦 |
| 老鸟如何追求快捷操作电脑 | 点击该处自动跳转查看哦 |
| 未来会写什么文章? | 预告链接 |
|---|---|
| 一文读懂 XX? | 点击该处自动跳转查看哦 |
| 2025年终总结 | 点击该处自动跳转查看哦 |
| 一图读懂 XX? | 点击该处自动跳转查看哦 |
