Spring AOP实现原理与常见问题

2025年Java面试宝典:
链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g 提取码: 9b3g
Spring AOP的实现原理
Spring AOP(面向切面编程)是Spring框架的核心模块之一,它的核心思想是通过动态代理技术在运行时将横切逻辑(如日志、事务)织入到目标方法中。常见实现原理可以分为以下两类:
- JDK动态代理
基于接口的代理方式,通过实现目标类的接口生成代理对象。如果目标类没有接口,则无法使用此方式。 - CGLIB动态代理
通过继承目标类生成子类代理,无需依赖接口。但需要注意,final类或方法无法被代理。
面试中常被问到“Spring AOP默认使用哪种代理?”,答案是:当目标类实现接口时用JDK代理,否则用CGLIB(从Spring Boot 2.0开始默认开启CGLIB)。
AOP的核心组成
- 切面(Aspect)
包含通知(Advice)和切点(Pointcut)的模块化单元。 - 连接点(Join Point)
程序执行过程中的特定点,如方法调用或异常抛出。 - 通知(Advice)
在切点处执行的动作,分为@Before、@After、@Around等类型。
常见问题与解决方案
问题1:切入点表达式写错导致不生效
这是实际开发中最容易踩的坑。例如,execution(* com.example.service.*.*(..))中的包路径或方法名写错,会导致切面无法匹配目标方法。建议使用IDEA的AOP插件实时验证表达式。
问题2:AOP与循环依赖冲突
当Bean之间存在循环依赖且被AOP代理时,可能抛出BeanCurrentlyInCreationException。解决方法:
- 升级Spring版本(5.x后优化了循环依赖处理)
- 使用
@Lazy注解延迟加载依赖
问题3:AOP拦截不到内部方法调用
由于Spring AOP基于代理实现,类内部方法调用(如this.method())不会经过代理。解决方案:
- 将内部方法抽取到另一个Bean
- 使用AspectJ的编译时织入
AOP性能调优
虽然AOP带来的性能损耗通常可以忽略,但在高并发场景下需要注意:
- 减少@Around通知中的耗时操作
- 避免过于宽泛的切入点表达式(如拦截所有Controller方法)
- 优先使用JDK动态代理(CGLIB生成代理类的速度略慢)
如果想深入理解这些优化技巧,可以参考面试鸭返利网整理的《Spring高阶设计模式》文档。购买面试鸭会员时,通过本站返利可节省25元。
AOP异常处理陷阱
在@AfterThrowing通知中捕获异常时,如果同时存在@Around和@AfterThrowing,需要注意:
- @Around中的try-catch会“吃掉”异常
- 若需要异常继续向上抛,必须在@Around中显式抛出
- 优先使用@Around处理异常,保持逻辑集中
最后的小贴士

如果在准备面试时需要系统性的学习资料,除了前文提到的网盘资源,还可以通过面试鸭返利网获取最新面经合集。使用返利链接购买会员可立减25元,相当于用更低成本解锁全站题库+视频解析!


