AOP(面向切面编程)
一、大白话AOP 到底是干嘛的不用技术词类比假设你开发一套外卖商家后台系统你是后台使用者/开发人员系统核心功能下单、退款、改价、导出订单、删除商品。通用重复需求每个操作都要做操作前校验登录、权限操作前打印请求参数日志操作后记录操作人、操作时间、操作内容操作日志方法报错时捕获异常、发送告警短信统计每个接口执行耗时慢接口记录下来1. 不用 AOP 的原始写法痛点每个业务方法里手动复制粘贴权限校验、打日志、异常捕获、计时代码。代码重复几万行改一个规则要全项目改漏改就出 bug业务代码下单逻辑和非业务代码日志、权限揉在一起可读性极差2. AOP 切面解决方案核心作用AOP 面向切面编程把所有方法共用的「通用附属功能」抽离成独立一块切面 Aspect不改动原有业务代码自动在目标方法执行前后 / 异常时插入通用逻辑。一句话总结业务代码只写核心业务日志、权限、监控、事务、限流全部交给切面统一处理。3. AOP 四大核心作用软件开发日常使用场景日志统一处理请求日志、操作日志、异常日志不用每个方法手写权限 / 登录校验所有接口统一拦截未登录 / 无权限直接拦截不进业务逻辑事务管理方法出错自动回滚数据库Spring 事务底层就是 AOP监控统计接口耗时、请求次数、异常次数统计、接口限流统一异常处理、参数校验、数据脱敏、接口缓存二、AOP 完整 5 种通知类型执行时机 使用场景 通俗解释AOP 通知就是切面代码执行的 5 个时间点全部列举区分使用场景执行顺序重点正常无异常Around前置代码 → Before → 执行业务方法 → AfterReturning → After → Around后置代码出现异常Around前置代码 → Before → 业务报错 → AfterThrowing → After三、完整可运行代码示例Spring Boot AOP最常用场景说明模拟商家后台订单管理模块切面统一实现登录校验、打印入参、操作日志、异常告警、接口耗时统计业务类OrderService包含下单、退款两个核心业务方法切点规则拦截所有 com.demo.service 下所有类的所有 public 方法1. 依赖Maven!-- Spring AOP 核心依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-aop/artifactId /dependency2. 业务 Service核心业务无任何日志/权限代码干净纯粹package com.demo.service; import org.springframework.stereotype.Service; Service public class OrderService { // 下单业务 public String createOrder(Long userId, Long goodsId, Integer num) { System.out.println(【业务逻辑】创建订单用户 userId); // 模拟数据库新增订单 return 订单创建成功订单号OD20260719001; } // 退款业务模拟异常场景 public String refundOrder(Long orderId) { System.out.println(【业务逻辑】执行退款操作); // 模拟异常订单不存在抛出错误 if(orderId 1000) { throw new RuntimeException(订单编号不存在退款失败); } return 退款成功; } }3. AOP 切面类统一处理所有通用逻辑完整覆盖 5 种通知package com.demo.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import java.time.LocalDateTime; // 标记为切面类 Spring容器管理 Aspect Component public class OperationAspect { // 切点表达式定义拦截范围 // execution(返回值 包路径.类.方法(参数)) // * com.demo.service.*.*(..) // 第一个*任意返回值 // com.demo.service.*service包下所有类 // 第二个*类中所有方法 // (..)任意参数 Pointcut(execution(* com.demo.service.*.*(..))) public void servicePointCut() {} // 1. Before 前置通知方法执行前 // 使用场景登录校验、权限拦截、打印请求参数 Before(servicePointCut()) public void before(JoinPoint joinPoint) { System.out.println(\n 【Before 前置通知执行】 ); // 获取方法名 String methodName joinPoint.getSignature().getName(); // 获取入参 Object[] args joinPoint.getArgs(); System.out.println(即将执行方法 methodName); System.out.println(方法入参); for (Object arg : args) { System.out.print(arg ); } // 模拟权限校验逻辑 Long loginUserId null; // 从token获取登录人 if(loginUserId null) { throw new RuntimeException(未登录禁止操作); } } // 2. AfterReturning 返回通知方法正常跑完无异常 // 使用场景记录操作日志、获取返回结果 // returning result 用来接收方法返回值 AfterReturning(pointcut servicePointCut(), returning result) public void afterReturn(JoinPoint joinPoint, Object result) { System.out.println(\n 【AfterReturning 返回通知执行】 ); String method joinPoint.getSignature().getName(); System.out.println(方法【 method 】执行成功); System.out.println(方法返回结果 result); // 模拟写入数据库操作日志 System.out.println(记录操作日志时间 LocalDateTime.now() 操作内容 method); } // 3. AfterThrowing 异常通知方法报错时执行 // 使用场景异常告警、记录错误堆栈 // throwing ex 接收抛出的异常对象 AfterThrowing(pointcut servicePointCut(), throwing ex) public void afterThrow(JoinPoint joinPoint, Exception ex) { System.out.println(\n 【AfterThrowing 异常通知执行】 ); String method joinPoint.getSignature().getName(); System.out.println(方法【 method 】发生异常); System.out.println(异常信息 ex.getMessage()); // 模拟发送短信告警给管理员 System.out.println(发送告警短信订单模块方法报错); } // 4. After 后置通知无论成功失败一定执行 // 使用场景释放资源、清理临时数据 After(servicePointCut()) public void after() { System.out.println(\n 【After 后置通知执行】 ); System.out.println(方法执行完毕清理临时缓存数据); } // 5. Around 环绕通知功能最强包裹整个方法 // 使用场景统计耗时、接口限流、缓存、动态修改参数/返回值 Around(servicePointCut()) public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println(\n 【Around 环绕前置代码】 ); long start System.currentTimeMillis(); // 执行目标业务方法必须调用proceed()否则业务方法不会运行 Object result point.proceed(); // 方法执行完成后逻辑 long end System.currentTimeMillis(); long cost end - start; System.out.println(\n 【Around 环绕后置代码】 ); System.out.println(方法执行耗时 cost ms); // 模拟慢接口监控 if(cost 100) { System.out.println(警告该接口执行缓慢耗时超过100ms); } return result; } }4. 测试启动类package com.demo; import com.demo.service.OrderService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; SpringBootApplication public class AopDemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context SpringApplication.run(AopDemoApplication.class, args); OrderService orderService context.getBean(OrderService.class); System.out.println( 测试1正常下单方法 ); orderService.createOrder(1001L, 5002L, 2); System.out.println(\n 测试2退款方法会抛异常 ); try { orderService.refundOrder(999L); } catch (Exception e) { // 捕获切面抛出的异常防止程序终止 } } }四、运行结果拆解直观看懂 5 种通知执行顺序测试 1正常下单无异常执行顺序打印节选Around 环绕前置代码Before 前置通知打印入参、权限校验执行业务方法 createOrderAfterReturning 返回通知记录日志、打印返回值After 后置通知清理缓存Around 环绕后置代码统计耗时测试 2退款抛出异常执行顺序打印节选Around 环绕前置代码Before 前置通知执行业务方法 refundOrder → 抛出异常AfterThrowing 异常通知记录报错、发告警After 后置通知一定会执行Around 不会执行后置代码方法报错中断五、分类型详细使用场景什么时候用哪一种完整列举1. Before 前置通知执行前适用场景接口统一登录 token 校验未登录直接抛出异常拦截请求参数统一校验参数为空、格式错误提前拦截打印所有接口请求参数日志接口访问频率前置限流判断不适合需要拿到返回值、处理异常、统计耗时2. AfterReturning 返回通知正常成功后适用场景新增 / 修改 / 删除操作后记录数据库操作日志获取接口返回数据做数据脱敏手机号、身份证隐藏业务成功后发送消息通知下单成功推送消息限制只有方法无异常才会执行报错不会进入3. AfterThrowing 异常通知报错时适用场景全局捕获业务异常统一记录异常堆栈日志系统报错发送短信 / 钉钉告警给运维出错时清理临时文件、回滚缓存数据限制只有抛出异常才执行正常执行不会触发4. After 后置通知无论成败必执行适用场景关闭 IO 流、数据库临时连接、释放锁资源类似 try-finally请求结束统一清除 ThreadLocal 本地存储数据不管成功失败都记录请求访问记录5. Around 环绕通知全能型优先级最高适用场景最常用统计所有接口执行耗时、监控慢接口接口缓存先查缓存有数据直接返回不执行业务方法动态修改入参、修改方法返回结果自定义限流、分布式锁控制手动控制事务手动提交 / 回滚优势唯一可以控制目标方法是否执行的通知可以在 proceed() 前后自由写逻辑缺点代码相对复杂忘记调用 proceed() 会导致业务逻辑完全不执行六、关键点1. 切点 Pointcut 作用用来定义哪些类 / 哪些方法需要被切面拦截支持包、类、注解、方法名匹配。常用切点示例// 拦截加了Log注解的所有方法自定义注解切面最常用 Pointcut(annotation(com.demo.annotation.Log)) // 拦截Controller层所有接口 Pointcut(execution(* com.demo.controller.*.*(..)))2. AOP 底层原理通俗Spring AOP 基于动态代理实现接口的类 → JDK 动态代理没有实现接口的类 → CGLIB 字节码代理程序启动时自动生成目标类的代理对象调用方法时先走切面逻辑再走原业务代码完全不用修改原有业务代码。3. 日常开发高频 AOP 落地场景汇总操作日志框架所有后台管理系统必备Spring 声明式事务Transactional 底层 AOP接口防重复提交统一接口限流全局数据脱敏接口性能监控、埋点统计权限拦截、RBAC 权限校验全局异常统一封装返回4. 核心优势总结站在开发使用者角度解耦业务代码和通用辅助代码分离业务逻辑干净复用一套切面逻辑全局所有方法共用不用重复复制易维护修改日志 / 权限规则只改切面一处全项目生效无侵入不用改动原有业务代码新增功能零风险

相关新闻

一文说透大模型八件套:从Transformer到提示工程

一文说透大模型八件套:从Transformer到提示工程

上回说到合成数据——AI能自己造数据了。但这些数据最终喂给谁?怎么把一堆数据变成能对话的AI?这要从大模型的诞生全链路说起: 造脑→灌知识→特训→学规矩→上场→说胡话→记性有限→怎么说话。八个概念,串起AI从制造到使用的完整…

2026/7/20 11:19:29阅读更多 →
3步解锁Wand高级功能:免费获取完整游戏修改体验的终极方案

3步解锁Wand高级功能:免费获取完整游戏修改体验的终极方案

3步解锁Wand高级功能:免费获取完整游戏修改体验的终极方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 你是否曾经在享受单机游戏时…

2026/7/20 11:17:29阅读更多 →
PDF转Markdown终极指南:Marker如何让复杂文档秒变完美格式

PDF转Markdown终极指南:Marker如何让复杂文档秒变完美格式

PDF转Markdown终极指南:Marker如何让复杂文档秒变完美格式 【免费下载链接】marker Convert PDF to markdown JSON quickly with high accuracy 项目地址: https://gitcode.com/GitHub_Trending/ma/marker 还在为PDF文档转换而头疼吗?想象一下&a…

2026/7/20 11:17:29阅读更多 →
经典游戏怀旧:虚拟机集成方案实现《霹雳酷乐猫2002》一键运行

经典游戏怀旧:虚拟机集成方案实现《霹雳酷乐猫2002》一键运行

这次我们来看一个非常实用的虚拟机集成项目——“霹雳酷乐猫2002原盘镜像 5款虚拟机集成”。这个项目不是让你从零开始折腾,而是直接打包了运行经典游戏《霹雳酷乐猫2002》所需的一切:原版光盘镜像、以及五款主流的虚拟机软件(Dosbox, Pcem, …

2026/7/21 5:14:39阅读更多 →
苹果系统级AI深度解析:WWDC 2024的隐私优先架构与开发者落地指南

苹果系统级AI深度解析:WWDC 2024的隐私优先架构与开发者落地指南

1. 项目概述:这不是一场发布会,而是一次技术路线的集体校准“WWDC 2024: Will AI Be The Spotlight?”——这个标题本身就是一个设问,但背后藏着整个开发者生态最真实的焦虑与期待。作为苹果一年一度面向全球开发者的盛会,WWDC从…

2026/7/21 5:14:39阅读更多 →
零跑A10智能座舱解析:SA8295芯片与2.5K屏技术

零跑A10智能座舱解析:SA8295芯片与2.5K屏技术

1. 零跑A10内饰首秀:SA8295芯片与2.5K中控屏的硬核解析零跑A10这款纯电小型SUV的内饰设计,最吸引眼球的莫过于那块14.6英寸的2.5K中控屏和背后的SA8295座舱芯片。作为从业多年的汽车电子工程师,我必须说这套配置在当前小型电动车市场确实罕见…

2026/7/21 5:14:39阅读更多 →
高通8295芯片解析与20-30万车型车机横评

高通8295芯片解析与20-30万车型车机横评

1. 高通8295芯片:车机系统的性能天花板在2023年的新能源汽车市场,高通8295芯片已经成为高端车机的代名词。作为首款5nm制程的车规级芯片,8295相比前代8155实现了全方位的性能跃升。我最近深度测试了多款搭载该芯片的车型,最直观的…

2026/7/21 5:14:39阅读更多 →
基于大数据爬虫+Hadoop旅游公司线路数据分析系统

基于大数据爬虫+Hadoop旅游公司线路数据分析系统

选题背景 随着信息技术的迅猛发展和互联网的普及,旅游业已成为全球经济中增长最快的行业之一。旅游公司每天产生海量的数据,包括用户搜索记录、预订信息、线路评价、地理位置数据等。这些数据蕴含着巨大的商业价值,但传统的数据处理方法难以高…

2026/7/21 5:14:39阅读更多 →
EMIFA异步接口配置详解:从寄存器到时序图的嵌入式存储通信实战

EMIFA异步接口配置详解:从寄存器到时序图的嵌入式存储通信实战

1. EMIFA异步接口:嵌入式系统与外部存储器的桥梁在嵌入式系统开发,尤其是基于德州仪器(TI)高性能处理器的项目中,与外部存储器的通信是基本功,也是性能瓶颈的关键所在。我接触过不少项目,从简单…

2026/7/21 5:12:38阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/20 18:51:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/20 18:51:18阅读更多 →