Spring Boot AOP(一) 入门与核心概念

复制代码
博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。
② 热榜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 性能统计、异常统一处理

通知执行顺序示意

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

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

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

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. 实战案例:日志 + 性能切面

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

多切面调用顺序示意

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 图帮助理解调用顺序和执行流程

结束语

👨‍💻 关于我

持续学习 | 追求真我

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

掘金点击访问Qiuner CSDN点击访问Qiuner GitHub点击访问Qiuner Gitee点击访问Qiuner

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

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

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

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

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

上一篇推荐 链接
Java程序员快又扎实的学习路线 点击该处自动跳转查看哦
一文读懂 AI 点击该处自动跳转查看哦
一文读懂 服务器 点击该处自动跳转查看哦
2024年创作回顾 点击该处自动跳转查看哦
一文读懂 ESLint配置 点击该处自动跳转查看哦
老鸟如何追求快捷操作电脑 点击该处自动跳转查看哦
未来会写什么文章? 预告链接
一文读懂 XX? 点击该处自动跳转查看哦
2025年终总结 点击该处自动跳转查看哦
一图读懂 XX? 点击该处自动跳转查看哦
相关推荐
后端小张7 小时前
【JAVA进阶】鸿蒙开发与SpringBoot深度融合:从接口设计到服务部署全解析
java·spring boot·spring·spring cloud·华为·harmonyos·鸿蒙
carry杰7 小时前
Springboot3 + shardingsphere-jdbc5.5.2 按年月分表(动态创建表)
java·spring cloud
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ7 小时前
throw new Exception 如何指定返回code
java·开发语言
C雨后彩虹7 小时前
虚拟理财游戏
java·数据结构·算法·华为·面试
fegggye7 小时前
创建一个rust写的python库
开发语言·后端·rust
武子康7 小时前
Java-197 消息队列应用场景:缓存预热+限流排队+Redis Lua 扣库存+MQ 削峰填谷
java·redis·缓存·性能优化·消息队列·rabbitmq·java-rabbitmq
全靠bug跑7 小时前
Spring Cloud Gateway 实战:统一鉴权与用户信息全链路透传
java·开发语言·gateway·拦截器
述清-架构师之路8 小时前
【亲测可用】idea设置mvn默认版本路径,setting路径,仓库路径
java·ide·intellij-idea
泡泡以安10 小时前
【Android逆向工程】第3章:Java 字节码与 Smali 语法基础
android·java·安卓逆向