当前位置: 首页 > news >正文

Spring AOP:横切关注点的优雅解决方案

🌟 什么是 AOP?它和 OOP 有什么关系?

原文:
Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure.

✅ 理解:

  • OOP(面向对象编程) 的核心单位是 类(class) —— 把数据和行为封装在一起。
  • AOP(面向切面编程) 的核心单位是 切面(aspect) —— 它用来处理那些“横跨多个类”的通用问题。

比如:日志记录、事务管理、权限校验、缓存等这些功能,并不属于某一个具体的业务逻辑,但却几乎每个方法都要用到。这类问题被称为:

🔹 Cross-cutting Concerns(横切关注点)

传统 OOP 很难优雅地解决这些问题——如果在每个方法里都手动加日志或事务,代码会变得重复、难以维护。

而 AOP 就是为了解决这种“横切关注点”而生的!


🧩 Spring 中的 AOP 是做什么的?

原文:
Spring AOP is used to:

  • Provide declarative enterprise services (e.g., transaction management)
  • Let users implement custom aspects

✅ 实际用途:

  1. 声明式事务管理
    比如你在 Service 方法上加个 @Transactional 注解,Spring 自动帮你开启/提交/回滚事务,不需要写 try-catch 和 commit/rollback。

  2. 自定义切面(Custom Aspects)
    比如你想统计所有 service 方法的执行时间,可以用 AOP 写一个“耗时监控”的切面,自动织入到目标方法前后。

💡 好处:

  • 业务代码干净整洁
  • 公共逻辑集中管理
  • 易于修改和复用

🔑 核心术语详解(5.1 节)

术语英文含义类比
切面Aspect横切关注点的模块化,比如“事务”、“日志”一个独立的功能模块
连接点Join Point程序执行过程中的某个点,如方法调用、异常抛出在 Spring AOP 中,仅支持方法执行
通知Advice切面在某个连接点要执行的动作“在方法前打印日志”就是一个 advice
切入点Pointcut匹配哪些连接点的通知会被触发使用表达式匹配方法,例如:“所有以 save 开头的方法”
引入Introduction给目标类动态添加方法或字段让某个 Bean 实现额外接口
目标对象Target Object被代理的对象(被增强的对象)原始的 Service 对象
AOP 代理AOP ProxyAOP 框架创建的对象,用来实现切面功能JDK 动态代理 或 CGLIB 生成的子类
织入Weaving把切面应用到目标对象的过程就像把“日志功能”缝进原方法里

⚙️ 五种类型的 Advice(通知)

类型何时执行是否能阻止流程示例
前置通知
@Before
方法执行前可通过抛异常阻止权限检查
后置返回通知
@AfterReturning
方法成功返回后记录结果
异常通知
@AfterThrowing
方法抛出异常后异常日志
最终通知
@After
方法结束后(无论是否异常)清理资源(类似 finally)
环绕通知
@Around
方法前后都可以控制✅ 可决定是否继续执行性能监控、缓存读写

📌 特别强调:

  • @Around 是最强大的,但也是最容易出错的(必须记得调用 proceed(),否则原方法不会执行)。
  • 推荐原则:用最简单的能满足需求的通知类型。能用 @AfterReturning 就不要用 @Around

🛠️ Spring AOP 的能力与目标(5.2 节)

重点摘要:

  • Spring AOP 是纯 Java 实现,无需特殊编译器。
  • 只支持 方法级别的拦截(不支持字段访问拦截)。
  • IoC 容器深度集成,切面本身也可以是 Spring Bean。
  • 不是为了取代 AspectJ,而是为了和 IoC 配合解决企业开发常见问题。
  • 如果你需要更强大的 AOP(如构造函数拦截、字段访问),建议使用 AspectJ + Spring 集成

🎯 结论:

Spring AOP = 轻量级、易用、适合大多数 Web 应用场景
AspectJ = 更强大、更复杂、适合精细控制

它们可以共存!Spring 支持混合使用。


🔁 AOP 代理机制(5.3 节)

Spring AOP 默认使用两种代理方式:

代理方式条件特点
JDK 动态代理目标类实现了接口基于接口代理,安全稳定
CGLIB 代理目标类没有实现接口通过生成子类来代理,性能略低

🔧 默认策略:

  • 如果有接口 → 使用 JDK 动态代理
  • 如果没接口 → 使用 CGLIB
  • 也可强制指定使用 CGLIB(通过配置)

⚠️ 关键理解:

Spring AOP 是基于代理模式实现的!

这意味着:

  • 实际运行的是一个“代理对象”,而不是原始对象。
  • 只有通过 Spring 容器调用的方法才会被拦截。
  • 自调用(this.method())不会触发 AOP!因为绕过了代理。

✅ 正确姿势:

@Service
public class UserService {@Autowiredprivate UserService self; // 注入自己(代理)public void business() {self.coreLogic(); // 通过代理调用,AOP 生效}@Transactionalpublic void coreLogic() {// ...}
}

💡 总结:如何通俗理解 Spring AOP?

想象一下你要给一栋大楼的所有房间安装摄像头(监控):

  • ❌ OOP 方式:进每个房间手动装摄像头 → 重复劳动,耦合度高
  • ✅ AOP 方式:统一部署一套“监控系统”,自动对所有指定房间进行监控

👉 AOP 就是这套“自动化监控系统”。

场景AOP 实现
统计方法耗时@Around 包裹方法,记录开始/结束时间
日志记录@Before 打印参数,@AfterReturning 打印结果
事务控制@Around 加事务边界
权限验证@Before 检查用户身份

📚 如何选择 AOP 风格?

Spring 提供两种写法:

风格特点推荐场景
@AspectJ 注解风格写法直观,像写普通类大多数项目推荐
XML Schema 风格全部用 XML 配置老项目兼容、不想加注解

📌 当前主流做法:使用 @Aspect + @Before/@After/@Around 注解。


✅ 快速示例:用 AOP 记录方法耗时

@Aspect
@Component
public class LogAspect {@Around("execution(* com.example.service.*.*(..))")public Object logTime(ProceedingJoinPoint pjp) throws Throwable {long start = System.currentTimeMillis();Object result = pjp.proceed(); // 执行原方法long elapsed = System.currentTimeMillis() - start;System.out.println(pjp.getSignature() + " took " + elapsed + "ms");return result;}
}

只要加上这个类,所有 service 包下的方法都会自动打印耗时!


🎯 最后总结一句话:

AOP 是一种设计思想,它让我们可以把分散在各处的公共逻辑(如日志、事务)抽取出来,集中管理,并通过“织入”机制自动应用到目标方法上,从而保持业务代码的纯净与高内聚。

Spring AOP 借助代理机制 + 注解/配置,让这种思想变得简单易用,特别适合企业级 Java 应用开发。


如果你正在学习 Spring,掌握 AOP 是迈向高级开发者的重要一步。建议动手写一个日志切面或权限切面试试看!

需要我根据你的实际项目场景给出 AOP 示例吗?欢迎继续提问 😊

http://www.dtcms.com/a/532072.html

相关文章:

  • 如何申请网站空间和注册域名鞋子软文推广300字
  • 基于AutoDL远端服务器在pycharm复现:具身智能论文pai0
  • 如何看访问网站的dns网站开发难不难
  • 数据结构·堆
  • 阮一峰《TypeScript 教程》学习笔记——类型映射
  • 需要做网站建设和推广网站地图插件
  • PyCharm 设置 Tabs and Indents
  • Spring Boot3零基础教程,生命周期监听,自定义监听器,笔记59
  • 【SpringBoot】详解Maven的操作与配置
  • 【C++】STL容器--priority_queue的使用与模拟实现
  • 【系统分析师】高分论文:论需求分析方法及应用(电子商务门户网站系统)
  • 【大模型应用开发 6.LangChain多任务应用开发】
  • 泰安最好的网站建设公司怎么通过做网站赚钱吗
  • 初识C语言15.文件操作
  • 聊聊连续、递增
  • 9款上班打卡软件测评:帮你选出最适合企业的工具
  • 建站服务网络公司建设宣传网站上的请示
  • Mem0 使用案例学习总结 - 记忆化应用结构
  • 如何自动清理 Linux 临时文件 ?
  • C++容器forward_list
  • 茂名网站建设培训品牌宣传网站
  • 油漆工找活做的网站网站免费建设
  • TcpClinet
  • Appium+Python+Android+Nodejs环境安装
  • SCDN:互联网时代网站安全的安全保障
  • Linux小课堂: Apache服务在CentOS上的安装与基础配置指南
  • Gorm(八)预加载方式
  • 网站开发与设计的实训场地WordPress无法自动推送
  • 【找指针数组最大值】2022-11-24
  • 自己做网站能赚钱吗做spa的网站怎么推广