Spring AOP底层实现(面试版)

引言

大家好啊,今天我们来讲一下面试中常常遇到的问题--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.ProxyInvocationHandler 实现,代理类的父类是Proxy 。方法调用时,通过 invoke() 方法拦截,并在其中加入切面逻辑。

Java不允许多继承,代理对象的父类是Proxy,所以只能基于接口实现。

2. CGLIB 动态代理(基于子类)

当目标类 没有实现接口 时,Spring 默认使用 CGLIB。CGLIB 通过继承目标类,生成子类(代理类),并重写其非 final 方法。代理类在重写的方法中插入切面逻辑。需要引入 cglib 依赖(Spring Boot 中已自动包含)。

总的来说,无论是哪种动态代理,执行相关bean的增强方法时,都是执行相关代理对象的方法,里面包含了增强逻辑和原有逻辑。

Spring AOP的织入时机

Spring AOP 是 运行时代理(Runtime Weaving),不是编译时或类加载时织入(如 AspectJ)。

具体流程:

  1. 容器启动时,解析所有 @Aspect 切面类。
  2. 根据 @Pointcut 表达式匹配目标 Bean 的方法。
  3. 对匹配的 Bean 创建代理对象(JDK 或 CGLIB)。
  4. 将代理对象注册到 Spring 容器中,后续注入的是代理对象而非原始对象。
  5. 调用方法时,通过代理对象触发通知逻辑。

这个流程上面说过了,这里再按步骤说一遍,但是重点说的是代理时机,是运行时代理!!!!

总结

Spring AOP 的底层原理可以概括为:

通过动态代理(JDK 或 CGLIB)在运行时为目标 Bean 生成代理对象,并在方法调用前后织入切面逻辑,从而实现非侵入式的功能增强。

这种设计既保持了代码的清晰性,又实现了关注点分离,是 Spring 框架解耦思想的重要体现

相关推荐
NAGNIP14 小时前
多个 GitHub 账户SSH 密钥配置全攻略
后端
NAGNIP14 小时前
Windows命令行代码自动补全详细步骤
后端
.鸣14 小时前
set和map
java·学习
追逐时光者14 小时前
精选 8 款 .NET 开源、前后端分离的快速开发框架,提高开发生产效率!
后端·.net
ha_lydms14 小时前
5、Spark函数_s/t
java·大数据·python·spark·数据处理·maxcompute·spark 函数
用户479492835691515 小时前
性能提升 4000%!我是如何解决 运营看板 不能跨库&跨库查询慢这个难题的
数据库·后端·postgresql
黄河滴滴15 小时前
java系统变卡变慢的原因是什么?从oom的角度分析
java·开发语言
侠客行031715 小时前
Mybatis二级缓存实现详解
java·mybatis·源码阅读
老华带你飞15 小时前
农产品销售管理|基于java + vue农产品销售管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
Edward1111111116 小时前
tomcat_servlet
java·servlet·tomcat