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

0 阅读5分钟

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 ProxyBean 有接口基于 Proxy.newProxyInstance() 生成实现接口的匿名类
CGLIBBean 无接口基于 ASM 生成子类并覆写方法

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

@ConditionalOnClass({ EnableAspectJAutoProxy.class })

AI写代码java
运行
1

而真正的 AOP 代理创建由:

AnnotationAwareAspectJAutoProxyCreator

来完成。


2. JDK vs CGLIB:本质与差异

关键差异表格:

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

Spring 的默认策略逻辑为:

if (hasUserSuppliedProxyInterfaces()) {
    return JDK dynamic proxy;
} else {
    return CGLIB proxy;
}

AI写代码java
运行
12345

3. AOP 核心入口:AnnotationAwareAspectJAutoProxyCreator

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

它[继承关系]如下:

BeanPostProcessor

AbstractAutoProxyCreator

ProxyCreatorSupport

AnnotationAwareAspectJAutoProxyCreator

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

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

流程对应:

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

AI写代码
1

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

代理创建的核心方法在:

AbstractAutoProxyCreator#postProcessAfterInitialization

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;
}

AI写代码java
运行
123456789101112

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

这意味着:

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


5. MethodInterceptor 调用链模型

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

List<MethodInterceptor> interceptors

AI写代码java
运行
1

执行流程如下:

ClientProxyInterceptor1Interceptor2Target调用方法invoke()invoke()原始方法调用返回返回返回返回结果ClientProxyInterceptor1Interceptor2Target

Spring 构建的链条类似:

ExposeInvocationInterceptor
 AspectJAroundAdvice
 MethodBeforeAdvice
 AfterReturningAdvice

AI写代码java
运行
1234

6. ProxyFactory 与 AdvisedSupport

Spring 的代理对象都来自:

ProxyFactory

AI写代码
1

其核心结构:

public class ProxyFactory extends ProxyCreatorSupport {
    ...
}

AI写代码java
运行
123

而管理 AOP 配置信息的是:

AdvisedSupport

AI写代码
1

包含:

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

创建代理示例:

ProxyFactory proxyFactory = new ProxyFactory(target);
proxyFactory.addAdvice(new LogMethodInterceptor());
Object proxy = proxyFactory.getProxy();

AI写代码java
运行
123

7. JDK [动态代理]源码解析

关键入口:

Proxy.newProxyInstance(classLoader, interfaces, invocationHandler)

AI写代码java
运行
1

Spring 使用的 InvocationHandler 是:

JdkDynamicAopProxy

AI写代码
1

主要实现如下:

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();
}

AI写代码java
运行
123456789101112

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


8. CGLIB 动态代理源码解析

使用:

Enhancer

AI写代码
1

核心逻辑:

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new MethodInterceptor() {});

AI写代码java
运行
123

Spring 中的 CGLIB 代理实现是:

CglibAopProxy.DynamicAdvisedInterceptor

AI写代码
1

核心代码:

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();
}

AI写代码java
运行
12345678

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


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

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

spring-boot-autoconfigure

AI写代码
1

入口类:

AopAutoConfiguration

AI写代码
1

其中启用了:

@EnableAspectJAutoProxy(proxyTargetClass = false)

AI写代码java
运行
1

说明:

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

AI写代码java
运行
1

则强制 CGLIB。


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

1)定义增强

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;
    }
}

AI写代码java
运行
123456789

2)创建代理

@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();
}

AI写代码java
运行
12345678910111213

3)运行输出:

Before: hello
hello
After: hello

AI写代码
123

11. 完整 AOP 创建链

有切面

JDK

CGLIB

Bean 创建完成

postProcessAfterInitialization

获取 Advisor 列表

选择代理方式

JdkDynamicAopProxy

CglibAopProxy

构建 MethodInterceptor 链

生成代理对象

返回代理 Bean


12. JDK vs CGLIB 对比总结表

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