Skip to Content
面试题库Spring Core[面试题] Spring AOP 是如何生成代理对象的?JDK 动态代理和 CGLIB 有什么区别?

[面试题] Spring AOP 是如何生成代理对象的?JDK 动态代理和 CGLIB 有什么区别?

📖 版块 A:知识讲解版 (温故知新)

  • Spring AOP 的本质

    1. Spring AOP 是基于代理模式实现的。
    2. 它不会直接修改原始类,而是为目标对象生成一个代理对象,再把增强逻辑织入到代理对象的调用链里。
  • 生成代理对象的大体流程

    1. Spring 在 Bean 初始化阶段,通过自动代理创建器判断当前 Bean 是否需要增强。
    2. 如果需要,会先收集目标类、Advisor、Interceptor 等信息。
    3. 再借助 ProxyFactoryAopProxy 生成最终代理对象。
  • JDK 动态代理

    1. 依赖接口。
    2. 如果目标类实现了接口,Spring 通常优先使用 JDK 动态代理。
    3. 代理对象本质上实现了同样的接口。
  • CGLIB

    1. 基于继承生成子类代理。
    2. 目标类没有接口,或者显式要求类代理时,Spring 通常会使用 CGLIB。
    3. final 类或 final 方法无法被 CGLIB 正常增强。
  • 一句话区别

    1. JDK 动态代理是“基于接口代理”。
    2. CGLIB 是“基于子类代理”。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:Spring AOP 是如何生成代理对象的?JDK 动态代理和 CGLIB 有什么区别?

💬 高手逐字稿

Spring AOP 生成代理对象,本质上不是在业务代码执行时临时瞎搞,而是在 Bean 生命周期的初始化阶段,由 Spring 容器统一完成的。

更准确一点说,Spring 的自动代理创建器本身就是一个特殊的 BeanPostProcessor。它会在 postProcessAfterInitialization 这个阶段判断:当前这个 Bean 有没有需要织入的切面。如果没有,就把原始对象原样返回;如果有,就会收集目标类、Advisor、MethodInterceptor 这些信息,然后通过 ProxyFactory 生成一个代理对象,最后把代理对象返回给容器。

也就是说,后续放进容器里、被别的 Bean 注入和调用的,很多时候已经不是原始对象,而是代理对象了。

至于 JDK 动态代理和 CGLIB,本质差异在于生成代理的方式不同。

JDK 动态代理依赖接口,它会生成一个实现了同样接口的代理对象,所以前提是目标类至少有接口可用。 CGLIB 则是通过继承目标类,动态生成一个子类来做代理,所以即使目标类没有接口,也能做增强。

Spring 的默认策略通常是:

  • 如果目标类实现了接口,优先走 JDK 动态代理;
  • 如果没有接口,或者配置了强制使用类代理,就走 CGLIB。

这里顺手可以补一个容易加分的点:为什么 final 方法经常让 AOP 失效? 因为 CGLIB 是靠子类重写方法织入逻辑的,final 方法没法被重写,自然也就织不进去。

所以这道题最后最好总结成两句:

  1. Spring AOP 是在 Bean 初始化阶段,通过 BeanPostProcessor 把原始对象替换成代理对象的。
  2. JDK 动态代理靠接口,CGLIB 靠继承。
最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册