引言
大家好啊,今天我们来讲一下面试中常常遇到的问题--Spring AOP到底是什么,做了什么,使用的好处?许多人就回答一个基于代理模式和JDK动态代理就草草了事,面试官没有得到他想要的答案,自然一直向下深挖,如果面试者无法回答或者突然卡住,给予面试官的感觉就会很差。那么我们下面就来探讨一下吧。
Spring AOP是什么?好处是什么?
Spring AOP(面向切面编程)的底层原理主要基于 代理模式(Proxy Pattern) ,并结合了 动态代理技术 来实现横切关注点(如日志、事务、安全等)与业务逻辑的解耦。其核心思想是在不修改源代码的前提下,对目标方法进行增强。
AOP能够减少重复代码与代码之间的耦合度,而且利于模块未来的扩展性和可维护性。
Spring AOP的底层原理?
Spring AOP核心点就是代理模式 + JDK动态代理/CGLIB 动态代理。
其实就两句话:
① 通过"代理对象"拦截方法调用
② 在方法执行前后织入增强逻辑
核心流程
-
容器启动
Spring 扫描到你的
@Aspect、@Around、@Before等增强方法,解析成 Advisor(通知器) 。 -
Bean 创建阶段
当某个 Bean 匹配了 Advisor 的 Pointcut 规则,Spring 会在 BeanPostProcessor(具体是
AnnotationAwareAspectJAutoProxyCreator) 中决定 ------ 是否需要为这个 Bean 创建代理对象 。 -
代理对象创建
Spring 根据目标类是否有接口,选择:
- 有接口 → JDK 动态代理
- 无接口 → CGLIB 代理(基于子类)
-
代理对象拦截方法调用
当你调用
bean.xxx()时,其实调用的是代理对象 → 执行增强链 → 最后执行目标方法。简单来说,就是spring启动的时候会扫一遍那些AOP的切面注解,有bean匹配了相关规则,就会根据是否有实现接口来给他匹配不同的动态代理模式。当该bean调用相关方法,则就会被拦截实现相关增强。

代理模式的选择
1. JDK 动态代理(基于接口)
要求目标类必须实现至少一个接口 。Spring 会为目标对象创建一个实现了相同接口的代理对象。使用 java.lang.reflect.Proxy 和 InvocationHandler 实现,代理类的父类是Proxy 。方法调用时,通过 invoke() 方法拦截,并在其中加入切面逻辑。
Java不允许多继承,代理对象的父类是Proxy,所以只能基于接口实现。
2. CGLIB 动态代理(基于子类)
当目标类 没有实现接口 时,Spring 默认使用 CGLIB。CGLIB 通过继承目标类,生成子类(代理类),并重写其非 final 方法。代理类在重写的方法中插入切面逻辑。需要引入 cglib 依赖(Spring Boot 中已自动包含)。
总的来说,无论是哪种动态代理,执行相关bean的增强方法时,都是执行相关代理对象的方法,里面包含了增强逻辑和原有逻辑。
Spring AOP的织入时机
Spring AOP 是 运行时代理(Runtime Weaving),不是编译时或类加载时织入(如 AspectJ)。
具体流程:
- 容器启动时,解析所有
@Aspect切面类。 - 根据
@Pointcut表达式匹配目标 Bean 的方法。 - 对匹配的 Bean 创建代理对象(JDK 或 CGLIB)。
- 将代理对象注册到 Spring 容器中,后续注入的是代理对象而非原始对象。
- 调用方法时,通过代理对象触发通知逻辑。
这个流程上面说过了,这里再按步骤说一遍,但是重点说的是代理时机,是运行时代理!!!!
总结
Spring AOP 的底层原理可以概括为:
通过动态代理(JDK 或 CGLIB)在运行时为目标 Bean 生成代理对象,并在方法调用前后织入切面逻辑,从而实现非侵入式的功能增强。
这种设计既保持了代码的清晰性,又实现了关注点分离,是 Spring 框架解耦思想的重要体现