Spring AOP全面详解
如果说 IOC 是 Spring 的核心,那么面向切面编程AOP就是 Spring 另外一个最为重要的核心@mikechen
AOP的定义
AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。
面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,如下图所示:\\
AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离,比如Spring的事务,通过事务的注解配置,Spring会自动在业务方法中开启、提交业务,并且在业务处理失败时,执行相应的回滚策略。
AOP的作用
AOP 采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。
简单的说,AOP 的作用就是保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能。
AOP的应用场景
- 日志记录
- 事务管理
- 权限验证
- 性能监测
AOP可以拦截指定的方法,并且对方法增强,比如:事务、日志、权限、性能监测等增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离。
Spring AOP的术语
在深入学习SpringAOP 之前,让我们先对AOP的几个基本术语有个大致的概念。
AOP核心概念
Spring AOP 通知分类
Spring AOP 织入时期
Spring AOP三种使用方式
AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:
1、定义普通业务组件
2、定义切入点,一个切入点可能横切多个业务组件
3、定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
方式1:使用Spring自带的AOP
配置通知时需实现org.springframework.aop包下的一些接口
- 前置通知:MethodBeforeAdvice
- 后置通知:AfterReturningAdvice
- 环绕通知:MethodInterceptor
- 异常通知:ThrowsAdvice
创建被代理对象
通知(Advice)
切入点(Pointcut):通过正则表达式描述指定切入点(某些 指定方法)
Advisor(高级通知) = Advice(通知) + Pointcut(切入点)
创建自动代理
方式2:使用Aspectj实现切面(普通POJO的实现方式)
导入Aspectj相关依赖
通知方法名随便起,没有限制
使用Aspectj实现切面,使用Spring AOP进行配置
方式3:使用Aspectj实现切面(基于注解的实现方式)
Spring AOP的实现原理
Spring的AOP实现原理其实很简单,就是通过动态代理实现的。
Spring AOP 采用了两种混合的实现方式:JDK 动态代理和 CGLib 动态代理。
- JDK动态代理:Spring AOP的首选方法。 每当目标对象实现一个接口时,就会使用JDK动态代理。目标对象必须实现接口
- CGLIB代理:如果目标对象没有实现接口,则可以使用CGLIB代理。
JDK动态代理
Spring默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理。
JDK实现动态代理需要两个组件,首先第一个就是InvocationHandler接口。
我们在使用JDK的动态代理时,需要编写一个类,去实现这个接口,然后重写invoke方法,这个方法其实就是我们提供的代理方法。
如下源码所示:
然后JDK动态代理需要使用的第二个组件就是Proxy这个类,我们可以通过这个类的newProxyInstance方法,返回一个代理对象。
生成的代理类实现了原来那个类的所有接口,并对接口的方法进行了代理,我们通过代理对象调用这些方法时,底层将通过反射,调用我们实现的invoke方法。
运行结果:
JDK动态代理优缺
优点
JDK动态代理是JDK原生的,不需要任何依赖即可使用;
通过反射机制生成代理类的速度要比CGLib操作字节码生成代理类的速度更快;
缺点
如果要使用JDK动态代理,被代理的类必须实现了接口,否则无法代理;
JDK动态代理无法为没有在接口中定义的方法实现代理,假设我们有一个实现了接口的类,我们为它的一个不属于接口中的方法配置了切面,Spring仍然会使用JDK的动态代理,但是由于配置了切面的方法不属于接口,为这个方法配置的切面将不会被织入。
JDK动态代理执行代理方法时,需要通过反射机制进行回调,此时方法执行的效率比较低;
CGLib代理
CGLIB组成结构
Cglib是一个强大的、高性能的代码生成包,它广泛被许多AOP框架使用,为他们提供方法的拦截,如下图所示Cglib与Spring等应用的关系:
- 最底层的是字节码
Bytecode
,字节码是Java为了保证“一次编译、到处运行”而产生的一种虚拟指令格式,例如iload_0、iconst_1、if_icmpne、dup等 - 位于字节码之上的是
ASM
,这是一种直接操作字节码的框架,应用ASM需要对Java字节码、Class结构比较熟悉 - 位于
ASM
之上的是CGLIB
、Groovy
、BeanShell
,后两种并不是Java体系中的内容而是脚本语言,它们通过ASM框架生成字节码变相执行Java代码,这说明在JVM中执行程序并不一定非要写Java代码----只要你能生成Java字节码,JVM并不关心字节码的来源,当然通过Java代码生成的JVM字节码是通过编译器直接生成的,算是最“正统”的JVM字节码 - 位于
CGLIB
、Groovy
、BeanShell
之上的就是Hibernate
、Spring AOP
这些框架了,这一层大家都比较熟悉 - 最上层的是Applications,即具体应用,一般都是一个Web项目或者本地跑一个程序
所以,Cglib的实现是在字节码的基础上的,并且使用了开源的ASM读取字节码,对类实现增强功能的。
原文链接:https://segmentfault.com/a/1190000042338414
__EOF__

本文链接:https://www.cnblogs.com/sugeek/articles/16603183.html
关于博主:编程菜鸟一只,希望每个今天胜过昨天,一步步走向技术的高峰!
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具