完整教程:Spring Boot AOP(一) 入门与核心概念

博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。
② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。
③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。
进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。
群公告里还有全网大赛约稿汇总/博客提效工具集/CSDN自动化运营脚本 有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。

img

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 常用方法

@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性能统计、异常统一处理

通知执行顺序示意

flowchart TD
    A[方法调用前] --> B[@Before 前置通知]
    B --> C[方法执行]
    C -->|成功| D[@AfterReturning 返回通知]
    C -->|异常| E[@AfterThrowing 异常通知]
    F[@After 后置通知] --> G[方法调用结束]
    D --> F
    E --> F

4. 简单切面示例

@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) 可以完全控制目标方法的执行:

  • 可以修改参数
  • 可以捕获异常
  • 可以修改返回值
  • 可以决定是否执行目标方法
@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;
}
}

流程图:环绕通知控制流程

flowchart TD
    A[方法调用] --> B[@Around 执行前逻辑]
    B --> C{是否执行目标方法?}
    C -->|执行| D[调用目标方法]
    C -->|不执行| E[直接返回]
    D --> F[@Around 执行后逻辑]
    F --> G[返回给调用方]
    E --> G

7. AOP 与 Bean 生命周期交互

Spring AOP 使用 BeanPostProcessor 在 Bean 初始化后生成代理:

BeanDefinition 注册
Bean 实例化
依赖注入
postProcessBeforeInitialization
初始化方法
postProcessAfterInitialization
需要代理?
创建代理对象
直接返回 Bean
代理对象注入到容器

核心类:

  • AnnotationAwareAspectJAutoProxyCreator
  • ProxyFactory / Enhancer
  • Advisor / Advice / Pointcut

8. 实战案例:日志 + 性能切面

@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);
}
}

多切面调用顺序示意

flowchart TD
    A[方法调用] --> B[LoggingAspect @Before]
    B --> C[PerformanceAspect @Around 前]
    C --> D[目标方法执行]
    D --> E[PerformanceAspect @Around 后]
    E --> F[LoggingAspect @AfterReturning]
    F --> G[返回调用方]

9. 本文小结

  • AOP 是处理横切关注点的强大机制
  • 切面 + 通知 + 切入点构成核心
  • 环绕通知最灵活,可控制方法执行前后
  • 多切面、Bean 生命周期、通知组合都需要清楚理解
  • Mermaid 图帮助理解调用顺序和执行流程

结束语


‍ 关于我

持续学习 | 追求真我

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 。

感谢订阅专栏 三连文章

image-20251011155556997

掘金点击访问QiunerCSDN点击访问QiunerGitHub点击访问QiunerGitee点击访问Qiuner

专栏简介
一图读懂系列图文并茂,轻松理解复杂概念
一文读懂系列深入浅出,全面解析技术要点
持续更新保持学习,不断进步
人生经验经验分享,共同成长

你好,我是Qiuner. 为帮助别人少走弯路而写博客

如果本篇文章帮到了你 不妨点个吧~ 我会很高兴的 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 。

代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦

如果你遇到了问题,自己没法解决,可以去我掘金评论区问。CSDN评论区和私信消息看不完 掘金消息少一点.

上一篇推荐链接
Java程序员快又扎实的学习路线点击该处自动跳转查看哦
一文读懂 AI点击该处自动跳转查看哦
一文读懂 服务器点击该处自动跳转查看哦
2024年创作回顾点击该处自动跳转查看哦
一文读懂 ESLint配置点击该处自动跳转查看哦
老鸟如何追求快捷操作电脑点击该处自动跳转查看哦
未来会写什么文章?预告链接
一文读懂 XX?点击该处自动跳转查看哦
2025年终总结点击该处自动跳转查看哦
一图读懂 XX?点击该处自动跳转查看哦

img

posted @ 2026-01-11 14:39  yangykaifa  阅读(2)  评论(0)    收藏  举报