Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)

复制代码
博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。
② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。
③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。
进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。
群公告里还有全网大赛约稿汇总/博客提效工具集/CSDN自动化运营脚本 有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。

文章目录

  • [Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)](#Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路))
  • [1. Spring Boot AOP 的本质是什么?](#1. Spring Boot AOP 的本质是什么?)
  • [2. JDK vs CGLIB:本质与差异](#2. JDK vs CGLIB:本质与差异)
  • [3. AOP 核心入口:AnnotationAwareAspectJAutoProxyCreator](#3. AOP 核心入口:AnnotationAwareAspectJAutoProxyCreator)
  • [4. 核心流程(源码级别)](#4. 核心流程(源码级别))
  • [5. MethodInterceptor 调用链模型](#5. MethodInterceptor 调用链模型)
  • [6. ProxyFactory 与 AdvisedSupport](#6. ProxyFactory 与 AdvisedSupport)
  • [7. JDK 动态代理源码解析](#7. JDK 动态代理源码解析)
  • [8. CGLIB 动态代理源码解析](#8. CGLIB 动态代理源码解析)
  • [9. Spring Boot 的 AOP 自动装配流程](#9. Spring Boot 的 AOP 自动装配流程)
  • [10. 实战:自定义 MethodInterceptor(接口级日志增强)](#10. 实战:自定义 MethodInterceptor(接口级日志增强))
  • [11. 完整 AOP 创建链](#11. 完整 AOP 创建链)
  • [12. JDK vs CGLIB 对比总结表](#12. JDK vs CGLIB 对比总结表)
  • [13. 参考文档](#13. 参考文档)
  • 结束语

Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)

目录

  1. AOP 本质与 Spring Boot 中的代理体系
  2. JDK 与 CGLIB 的本质区别与适用场景
  3. Spring AOP 代理创建入口:AnnotationAwareAspectJAutoProxyCreator
  4. AOP 代理的创建流程(源码级调用链)
  5. 方法拦截链 MethodInterceptor 调用模型深入解析
  6. ProxyFactory 与 AdvisedSupport 完整结构拆解
  7. JDK 动态代理源码解析
  8. CGLIB 子类增强源码解析
  9. Spring Boot 中的 AOP 自动装配是如何介入的?
  10. 实战:自定义 MethodInterceptor 实现接口级日志增强
  11. 流程图、调用链图
  12. 表格总结(JDK vs CGLIB)
  13. 参考文档

1. Spring Boot AOP 的本质是什么?

AOP(面向切面)在 Spring Boot 中,本质上是:

🎯 用动态代理包装原始 Bean,让方法执行过程被增强。

核心是两个方案:

代理方式 适用场景 原理
JDK Dynamic Proxy Bean 有接口 基于 Proxy.newProxyInstance() 生成实现接口的匿名类
CGLIB Bean 无接口 基于 ASM 生成子类并覆写方法

Spring Boot 自动开启 AOP 的入口通常来自:

java 复制代码
@ConditionalOnClass({ EnableAspectJAutoProxy.class })

而真正的 AOP 代理创建由:

AnnotationAwareAspectJAutoProxyCreator

来完成。


2. JDK vs CGLIB:本质与差异

关键差异表格:

项目 JDK 动态代理 CGLIB
代理方式 接口代理 子类代理
是否依赖接口 必须有接口 不需要接口
性能 调用成本低 生成类成本高,调用快
final 方法是否可代理 ❌ 不可 ❌ 也不可
复杂度 简单 高,依赖 asm
Spring 默认选择 有接口用 JDK 无接口用 CGLIB

Spring 的默认策略逻辑为:

java 复制代码
if (hasUserSuppliedProxyInterfaces()) {
    return JDK dynamic proxy;
} else {
    return CGLIB proxy;
}

3. AOP 核心入口:AnnotationAwareAspectJAutoProxyCreator

这是整个 AOP 的自动代理核心。

它继承关系如下:
BeanPostProcessor AbstractAutoProxyCreator ProxyCreatorSupport AnnotationAwareAspectJAutoProxyCreator

最终,它是一个 BeanPostProcessor,意味着:

⚠️ 代理是在 Bean 初始化阶段创建的,而不是在容器启动时创建的。

流程对应:

复制代码
postProcessBeforeInitialization → 目标Bean初始化 → postProcessAfterInitialization → 生成代理 Bean

4. 核心流程(源码级别)

代理创建的核心方法在:

AbstractAutoProxyCreator#postProcessAfterInitialization

java 复制代码
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (isInfrastructureClass(bean.getClass())) return bean;

    // 查找当前 Bean 需要应用的增强(Advice)
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean);

    if (specificInterceptors != DO_NOT_PROXY) {
        // 创建代理
        return createProxy(bean.getClass(), beanName, specificInterceptors, bean);
    }
    return bean;
}

🔥 关键点:代理不是提前创建,而是在初始化后替换 Bean!

这意味着:

⚠️ Bean 在初始化时是真实对象,但被注入到容器中的是代理对象。


5. MethodInterceptor 调用链模型

最终 AOP 逻辑依赖一个拦截链:

java 复制代码
List<MethodInterceptor> interceptors

执行流程如下:
Client Proxy Interceptor1 Interceptor2 Target 调用方法 invoke() invoke() 原始方法调用 返回 返回 返回 返回结果 Client Proxy Interceptor1 Interceptor2 Target

Spring 构建的链条类似:

java 复制代码
ExposeInvocationInterceptor
→ AspectJAroundAdvice
→ MethodBeforeAdvice
→ AfterReturningAdvice

6. ProxyFactory 与 AdvisedSupport

Spring 的代理对象都来自:

复制代码
ProxyFactory

其核心结构:

java 复制代码
public class ProxyFactory extends ProxyCreatorSupport {
    ...
}

而管理 AOP 配置信息的是:

复制代码
AdvisedSupport

包含:

  • 目标类
  • 目标对象
  • 方法拦截器列表
  • 代理方式(JDK/CGLIB)
  • 是否提前暴露代理

创建代理示例:

java 复制代码
ProxyFactory proxyFactory = new ProxyFactory(target);
proxyFactory.addAdvice(new LogMethodInterceptor());
Object proxy = proxyFactory.getProxy();

7. JDK 动态代理源码解析

关键入口:

java 复制代码
Proxy.newProxyInstance(classLoader, interfaces, invocationHandler)

Spring 使用的 InvocationHandler 是:

复制代码
JdkDynamicAopProxy

主要实现如下:

java 复制代码
public Object invoke(Object proxy, Method method, Object[] args) {
    List<Object> chain = this.advised.getInterceptors(method);

    if (chain.isEmpty()) {
        return method.invoke(this.advised.getTargetSource().getTarget(), args);
    }

    MethodInvocation invocation =
        new ReflectiveMethodInvocation(proxy, target, method, args, chain);

    return invocation.proceed();
}

🔍 JDK 代理核心:通过 InvocationHandler 包装方法调用。


8. CGLIB 动态代理源码解析

使用:

复制代码
Enhancer

核心逻辑:

java 复制代码
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new MethodInterceptor() {});

Spring 中的 CGLIB 代理实现是:

复制代码
CglibAopProxy.DynamicAdvisedInterceptor

核心代码:

java 复制代码
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
    List<Object> chain = this.advised.getInterceptors(method);

    MethodInvocation invocation =
        new CglibMethodInvocation(proxy, target, method, args, chain, methodProxy);

    return invocation.proceed();
}

💡 CGLIB 的特点:生成子类 & 使用 ASM 自动生成字节码。


9. Spring Boot 的 AOP 自动装配流程

在 Spring Boot 中,AOP 自动配置来自:

复制代码
spring-boot-autoconfigure

入口类:

复制代码
AopAutoConfiguration

其中启用了:

java 复制代码
@EnableAspectJAutoProxy(proxyTargetClass = false)

说明:

  • 如果 proxyTargetClass=false → 尽量使用 JDK 代理
  • 如果用户手动开启:
java 复制代码
@EnableAspectJAutoProxy(proxyTargetClass = true)

则强制 CGLIB。


10. 实战:自定义 MethodInterceptor(接口级日志增强)

1)定义增强

java 复制代码
public class LogInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before: " + invocation.getMethod().getName());
        Object result = invocation.proceed();
        System.out.println("After: " + invocation.getMethod().getName());
        return result;
    }
}

2)创建代理

java 复制代码
@Service
public class UserServiceImpl implements UserService {
    public void hello() {
        System.out.println("hello");
    }
}

@Bean
public UserService userServiceProxy(UserServiceImpl target) {
    ProxyFactory factory = new ProxyFactory(target);
    factory.addAdvice(new LogInterceptor());
    return (UserService) factory.getProxy();
}

3)运行输出:

复制代码
Before: hello
hello
After: hello

11. 完整 AOP 创建链

有切面 JDK CGLIB Bean 创建完成 postProcessAfterInitialization 获取 Advisor 列表 选择代理方式 JdkDynamicAopProxy CglibAopProxy 构建 MethodInterceptor 链 生成代理对象 返回代理 Bean


12. JDK vs CGLIB 对比总结表

维度 JDK 代理 CGLIB 代理
是否需要接口
性能 调用慢,创建快 调用快,创建慢
是否能代理 final 类
是否能代理 final 方法
Spring 默认选择 有接口 无接口
底层原理 反射 + InvocationHandler ASM + 字节码生成

13. 参考文档


结束语

👨‍💻 关于我

持续学习 | 追求真我

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
感谢订阅专栏 三连文章

掘金点击访问Qiuner CSDN点击访问Qiuner GitHub点击访问Qiuner Gitee点击访问Qiuner

专栏 简介
📊 一图读懂系列 图文并茂,轻松理解复杂概念
📝 一文读懂系列 深入浅出,全面解析技术要点
🌟持续更新 保持学习,不断进步
🎯 人生经验 经验分享,共同成长

你好,我是Qiuner. 为帮助别人少走弯路而写博客

如果本篇文章帮到了你 不妨点个 吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍

如果你遇到了问题,自己没法解决,可以去我掘金评论区问。CSDN评论区和私信消息看不完 掘金消息少一点.

上一篇推荐 链接
Java程序员快又扎实的学习路线 点击该处自动跳转查看哦
一文读懂 AI 点击该处自动跳转查看哦
一文读懂 服务器 点击该处自动跳转查看哦
2024年创作回顾 点击该处自动跳转查看哦
一文读懂 ESLint配置 点击该处自动跳转查看哦
老鸟如何追求快捷操作电脑 点击该处自动跳转查看哦
未来会写什么文章? 预告链接
一文读懂 XX? 点击该处自动跳转查看哦
2025年终总结 点击该处自动跳转查看哦
一图读懂 XX? 点击该处自动跳转查看哦
相关推荐
cmdch201742 分钟前
AWS亚马逊
java
TDengine (老段)43 分钟前
TDengine 字符串函数 GROUP_CONCAT 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
JavaBoy_XJ1 小时前
RabbitMQ 在 Spring Boot 项目中的完整配置指南
spring boot·rabbitmq·java-rabbitmq
Tony Bai1 小时前
Go 2025云原生与可观测年度报告:底层性能革新与生态固防
开发语言·后端·云原生·golang
断春风1 小时前
Java 集成 AI 大模型最佳实践:从零到一打造智能化后端
java·人工智能·ai
铅笔侠_小龙虾1 小时前
Java 模拟实现 Vue
java·开发语言·vue.js
咖丨喱1 小时前
【miracast连接优化】
后端·asp.net
淘源码d1 小时前
智慧工地企项一体化平台,Spring Cloud +UniApp 智慧工地源码,BIM+AI+物联网,施工全过程数字化智慧工地管理平台
java·人工智能·物联网·智慧工地·智慧工地源码·智慧工地app·数字工地
Victor3561 小时前
Redis(167)如何使用Redis实现分布式缓存?
后端