当前位置: 首页 > news >正文

【Spring底层分析】AOP的cligb代理和jdk代理

AOP的cligb代理和jdk代理

spring默认创建的是clibg代理对象,如果想要让spring创建jdk代理对象,那么需要:

1、确保目标类实现至少一个接口

2、配置Spring强制使用JDK代理,@EnableAspectJAutoProxy(proxyTargetClass = false)

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false) // 关键设置
public class AppConfig {// 配置类内容
}

cligb代理对象代理流程:

  1. Spring为某些Bean创建CGLIB代理对象
  2. 调用方法时实际调用代理对象的方法
  3. 代理对象执行intercept()方法
  4. 生成拦截器链(由多个MethodInterceptor组成)
  5. 链执行器按顺序执行拦截器链中的每个拦截器的invoke方法,实际就是调用增强方法。
  6. 在合适的时机调用原始目标方法

无论是创建CGLIB代理对象、还是执行intercept()方法,实际上都是CglibAopProxy类里的方法。

class CglibAopProxy implements AopProxy, Serializable{public Object getProxy() {}public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//这里可以具体看我的另一篇文章,有详细介绍源码:https://blog.csdn.net/m0_73866527/article/details/148384920?spm=1001.2014.3001.5501}
}

jdk代理对象代理流程:

  1. Spring为某些Bean创建jdk代理对象
  2. 调用方法时实际调用代理对象的方法
  3. 代理对象执行invoke()方法
  4. 生成拦截器链(由多个MethodInterceptor组成)
  5. 链执行器按顺序执行拦截器链中的每个拦截器的invoke方法,实际就是调用增强方法。
  6. 在合适的时机调用原始目标方法

无论是创建CGLIB代理对象、还是执行intercept()方法,实际上都是JdkDynamicAopProxy类里的方法。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler {public Object getProxy() {return getProxy(ClassUtils.getDefaultClassLoader());}public Object getProxy(@Nullable ClassLoader classLoader) {// 1. 获取目标接口Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);// 2. 关键:创建JDK代理实例return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}// 实现InvocationHandler接口public Object invoke(Object proxy, Method method, Object[] args) {// 拦截逻辑// 获取目标对象(原始Bean)Target target = getTarget();// 创建拦截器链 - 与你熟悉的CGLIB完全一致!List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// 创建方法调用链执行器MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 执行拦截器链 - 核心流程与你已知的CGLIB完全一致return invocation.proceed();}
}

在这里插入图片描述

在这里插入图片描述

这时候你肯定有疑惑,为什么代理对象执行目标方法时,会自动执行intercept方法或invoke方法?

在对象创建时通过字节码生成技术,将调用路径"刻印"在代理对象的DNA中,使得后续所有方法调用都能自动路由到正确的处理逻辑!

(这里留个坑,先不细挖了)

那么你又会有疑惑,为什么这两个代理方式差不多,为什么还需要有这两种代理方式呢?

维度JDK动态代理CGLIB代理差异影响
代理机制接口代理(实现相同接口)子类代理(继承目标类)根本设计哲学不同
目标要求必须实现接口类不能是final适用场景分化
性能特点创建快(≈15ns),调用慢(反射开销)创建慢(≈200ns),调用快(直接调用)高频调用场景选择关键
方法覆盖只能代理接口方法可代理所有非final方法功能覆盖范围不同
内存占用轻量级(约256字节)重量级(约1-2KB)资源敏感系统选择依据

- JDK代理是通过反射调用目标方法(因为代理对象和目标对象没有继承关系,只有共同的接口,所以只能反射调用目标对象的方法)。

- CGLIB代理是通过直接调用(通过方法索引,类似直接调用)父类(目标类)的方法(因为代理对象是目标对象的子类,所以可以调用父类方法)。

  • JDK代理 = "翻译官"模式
    • 需要懂双方语言(接口)
    • 每次沟通都要翻译(反射)
    • 适合临时简单任务
  • CGLIB代理 = "机械臂"模式
    • 直接嵌入操作环境(继承)
    • 预设精确操作指令(直接调用)
    • 适合高频重复任务

相关文章:

  • 网站建设公司华网天下买赠两年搜索推广是什么意思
  • 哪些网站可以在线做动图石家庄疫情最新情况
  • 哈尔滨专业做网站公司国家重大新闻
  • 网站开发工具和平台2023全民核酸又开始了
  • wordpress积分查看隐藏内容重庆seo霸屏
  • 陕西高端品牌网站建设免费网站的软件
  • 逆向入门(7)汇编篇-mul指令的学习
  • 《C++》命名空间简述
  • 云电脑,“死”于AI时代前夕 | 数智化观察
  • JVM(12)——详解G1垃圾回收器
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月24日第118弹
  • Python移除链表元素-虚拟节点
  • 植物小知识
  • [密码学实战]商密TLCP协议抓包解析与深度分析(二十九)
  • 云原生周刊:Argo CD v3.1 正式发布
  • git学习资源
  • 大模型时代的创业机遇
  • Linux 网络命名空间的奥秘:深入解析struct net与内核模块编译陷阱
  • Redis 分布式锁原理与实战-学习篇
  • DeepSeek智能总结 | 邓紫棋音乐版权纠纷核心梳理
  • Vue3+Spring boot 前后端防抖增强方案
  • 3.0 compose学习:MVVM框架+Hilt注解调用登录接口
  • 领域驱动设计(DDD)【9】之代码初始部分实现和问题解决
  • 仓颉语言语法特点、使用范围、编译及环境搭建:从零开始第一个cangjie程序
  • 变电站自动化系统有哪些设备?
  • 如何通过FEMFAT许可证进行数据分析和处理