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

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

文章目录

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..*.*(..))")publicObjectlogAround(ProceedingJoinPoint pjp)throwsThrowable{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@ComponentpublicclassLogAspect{@Before("execution(* com.example.service..*.*(..))")publicvoidlogBefore(JoinPoint joinPoint){System.out.println("前置通知: 调用方法 "+ joinPoint.getSignature().getName());}@AfterReturning(pointcut ="execution(* com.example.service..*.*(..))", returning ="result")publicvoidlogAfterReturning(JoinPoint joinPoint,Object result){System.out.println("返回通知: 方法返回值 "+ result);}@Around("execution(* com.example.service..*.*(..))")publicObjectlogAround(ProceedingJoinPoint pjp)throwsThrowable{long start =System.currentTimeMillis();System.out.println("环绕通知: 方法执行前");Object result = pjp.proceed();System.out.println("环绕通知: 方法执行后, 耗时 "+(System.currentTimeMillis()- start)+"ms");return result;}}

5. 方法调用流程示意

ClientProxyTarget调用方法执行 @Before调用目标方法返回结果执行 @AfterReturning 或 @AfterThrowing返回最终结果ClientProxyTarget


6. 环绕通知深入解析

环绕通知 (@Around) 可以完全控制目标方法的执行:

  • 可以修改参数
  • 可以捕获异常
  • 可以修改返回值
  • 可以决定是否执行目标方法
@Around("execution(* com.example.service..*.*(..))")publicObjectsecureAround(ProceedingJoinPoint pjp)throwsThrowable{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@ComponentpublicclassPerformanceAspect{@Around("execution(* com.example.service..*.*(..))")publicObjectmeasureTime(ProceedingJoinPoint pjp)throwsThrowable{long start =System.currentTimeMillis();Object result = pjp.proceed();long duration =System.currentTimeMillis()- start;System.out.println(pjp.getSignature()+" 耗时: "+ duration +"ms");return result;}}@Aspect@ComponentpublicclassLoggingAspect{@Before("execution(* com.example.service..*.*(..))")publicvoidlogBefore(JoinPoint joinPoint){System.out.println("调用方法: "+ joinPoint.getSignature().getName());}@AfterReturning(pointcut ="execution(* com.example.service..*.*(..))", returning ="result")publicvoidlogAfterReturning(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

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

专栏简介
📊 一图读懂系列图文并茂,轻松理解复杂概念
📝 一文读懂系列深入浅出,全面解析技术要点
🌟持续更新保持学习,不断进步
🎯 人生经验经验分享,共同成长
你好,我是Qiuner. 为帮助别人少走弯路而写博客

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

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

如果你遇到了问题,自己没法解决,可以去我掘金评论区问。ZEEKLOG评论区和私信消息看不完 掘金消息少一点.
上一篇推荐链接
Java程序员快又扎实的学习路线点击该处自动跳转查看哦
一文读懂 AI点击该处自动跳转查看哦
一文读懂 服务器点击该处自动跳转查看哦
2024年创作回顾点击该处自动跳转查看哦
一文读懂 ESLint配置点击该处自动跳转查看哦
老鸟如何追求快捷操作电脑点击该处自动跳转查看哦
未来会写什么文章?预告链接
一文读懂 XX?点击该处自动跳转查看哦
2025年终总结点击该处自动跳转查看哦
一图读懂 XX?点击该处自动跳转查看哦

Read more

Flutter 三方库 xpath_selector 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、精准的 HTML/XML 数据抓取与 Web 结构解析引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 xpath_selector 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、精准的 HTML/XML 数据抓取与 Web 结构解析引擎 在鸿蒙(OpenHarmony)系统的网络爬虫、自动化测试审计、或者是从复杂的第三方 Web 公告(HTML)中提取关键数据(如新闻标题、资产负债表)时,如何摆脱凌乱的正向正则(Regex),转而使用业界标准的 XPath 语法进行语义化选取?xpath_selector 为开发者提供了一套工业级的、基于 Dart 的 HTML/XML 结构化查询方案。本文将深入实战其在鸿蒙端数据治理中的应用。 前言 什么是 XPath Selector?

By Ne0inhk
OpenClaw dashboard命令后,无法登录web控制面板(在systemd服务无法启动的一些虚拟机里会碰到)

OpenClaw dashboard命令后,无法登录web控制面板(在systemd服务无法启动的一些虚拟机里会碰到)

先上结论 执行OpenClaw dashboard命令后,无法登录web控制面板,是因为OpenClaw的gateway服务没有起来。原来小龙虾OpenClaw 的命令没有学明白,先弄清楚命令: openclaw onboard 是配置 openclaw dashboard是显示web控制面板登录信息 openclaw gateway --verbose 是启动网关 openclaw gateway start是启动网关服务 问题就是因为这台系统的systemd没有起作用,导致openclaw的gateway服务没有起来,所以控制面板无法登录。 OpenClaw status Overview ┌─────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Item │ Value │ ├─────────────────┼────────────────────────────────────

By Ne0inhk

day20|学习前端

{{}}。相当于innerText v-bind:attr绑定属性值。 hooks是一个一个可以调用的函数。composition API 返回对象+解构 const{ sum,add,bigSum}=useSum() 一般组件放到components。路由组件放到pages,views文件夹 to路由:1、字符串写法。2、对象写法(name跳转,path跳转) 集中式状态(数据)管理pinia,redux,vuex 把共享的数据交给集中式管理, pinia落地的东西,就是store v-bind单项绑定。v-model双向绑定   function不缓存,computed计算属性缓存,只有依赖变才重新计算。 computed计算属性函数,根据已有响应式数据计算出新值,具有缓存的功能。 watch 入口文件main.ts App.vue根组件 一般组件导入和使用的方法 插值语法 vue3可以写vue2语法,在vue3里,选项式和组合式是共存的。旧语法可以读出setup东西,

By Ne0inhk
深入剖析:按下 F5 后,浏览器前端究竟发生了什么?

深入剖析:按下 F5 后,浏览器前端究竟发生了什么?

文章目录 * 概述 * 一、关键前提:三种导航方式的本质区别 * 二、核心概念:强缓存 vs 协商缓存 * 1. 强缓存(Strong Caching) * 2. 协商缓存(Revalidation Caching) * 三、F5 刷新全景流程图 * 四、F5 刷新的完整生命周期详解 * 阶段一:主文档(HTML)的缓存验证与获取 * 阶段二:HTML 解析与渲染流水线(Critical Rendering Path) * 阶段三:子资源(CSS/JS/IMG)的缓存处理 * 五、对比总结:F5 与其他操作的本质差异 * 六、给前端开发者的实践建议 * 七、结语 概述 在前端开发中,

By Ne0inhk