Spring 5.x 源码之旅-80事务CGLIB动态代理的秘密二

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

 

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

 

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

 

CGLIB代理方法执行基本流程

拦截器的intercept调用的秘密

一般我们在这里面做一些增强,然后调用原来的对象的方法,也就是methodProxy.invokeSuper,但是前面说了,传入参数o是代理对象,他是怎么调用原来的对象呢。:

MethodProxy的invokeSuper调用父类方法

其实看这个名字就知道是调用原方法,调用父类方法嘛,前面有继承嘛,对吧。但是事实是怎么样呢,我们来看看吧:

    	public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    		try {
    			init();//初始化fastClassInfo
    			FastClassInfo fci = fastClassInfo;
    			return fci.f2.invoke(fci.i2, obj, args);
    		}
    		catch (InvocationTargetException e) {
    			throw e.getTargetException();
    		}
    	}

MethodProxy的init创建FastClassInfo

FastClassInfo

这个类其实就是存放了两个FastClass对象,和两个索引,他们是什么,其实就是两个FastClass增强对象,和锁对应方法的索引。索引什么鬼,简单的说吧,JDK反射调用方法有很多检查,性能肯定有损耗,所以CGLIB就想能不能我再创建两个类,一个是有原方法的类,一个是代理方法的类,里面有很多方法对应的索引,如果我能获取一个方法的索引,根据索引可以调用对应类的方法,这样避免用反射调用,具体做法我后面会分析,现在知道个大概就好。

动态生成FastClass增强类

这里就是根据创建的信息CreateInfo,来创建被代理类和代理类的FastClass增强对象,而且是动态创建的,还用了双重检测,只会创建一次。

    private void init() {
    		if (fastClassInfo == null) {
    			synchronized (initLock) {
    				if (fastClassInfo == null) {
    					CreateInfo ci = createInfo;
    
    					FastClassInfo fci = new FastClassInfo();
    					fci.f1 = helper(ci, ci.c1);
    					fci.f2 = helper(ci, ci.c2);
    					fci.i1 = fci.f1.getIndex(sig1);
    					fci.i2 = fci.f2.getIndex(sig2);
    					fastClassInfo = fci;
    					createInfo = null;
    				}
    			}
    		}
    	}

此时我们看到两个增强的类,和两个索引,f1,i1对应的是被代理类的FastClass增强对象,f2,i2对应的是代理类的FastClass增强对象:


而且生成了字节码文件,就是EnhancerByCGLIB再增强FastClassByCGLIB,另外一个CglibObj$$FastClassByCGLIB$$2bb5f2d7是在前面创建代理的时候就创建了,只是前面没讲,现在讲:


这些FastClass增强类到底增强什么呢,其实是方法的调用,跟索引有关,他会根据方法签名去FastClass增强类获取相关的索引,因为所有的方法都在FastClass增强类里:


看到了吧,CglibObj$$FastClassByCGLIB$$2bb5f2d7里面f1方法的返回索引是0


看到了吧,CglibObj$$EnhancerByCGLIB$$ef630afc$$FastClassByCGLIB$$9f694f5b里面f1的方法的返回索引是13


这些方法前面字符串哪里来的啊,其实前面有,我就稍微提下:


namedesc拼起来的,这些都是生成字节码的时候根据方法生成的:


FastClass增强对象和方法索引都获取到了:

获取了之后怎么用呢,下篇讲啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值