JAVA基础:动态代理cglib原理(二)Fastclass 机制分析

提示:动态代理


前言

类型机制回调方式适用场景效率
JDK动态代理委托机制。代理类和目标类都实现了同样的接口。InvocationHandler持有目标类。代理类委托InvocationHandler去调用目标类原始方法反射目标类实现接口反射调用稍慢。
CGLIB动态代理继承机制。代理类继承了目标类并重写了目标方法,通过回调函数MethodInterceptor调用父类方法执行原始逻辑通过FastClass方法索引调用非final类,非final方法第一次调用因为要生成多个Class对象较]DK慢,但是调用时方法索引较反射方式快

本篇讲解通过FastClass方法索引调用中FastClass机制原理。


一、FastClass机制

JDK动态代理的拦截对象是通过反射的机制来调用被拦截方法的,反射的效率比较低,所以CGLIB采用了FastClass的机制来实现对被拦截方法的调用。

CGLIB共生成3个类,分别为代理类,代理类的FastClass,目标类的FastClass,FastClass机制就是对一个类的方法建立索引,通过索引来直接调用相应的方法。
在这里插入图片描述
FastClass并不是跟代理类一块生成的,而是在第一次执行MethodProxy invoke/invokeSuper时生成的并放在了缓存中。
在这里插入图片描述
在这里插入图片描述
下面用一个小例子来说明:

package com.kkk.demo1;

/**
 * @author Kkk
 * @date 2023/2/21
 * @Describe: 演示 FastClass机制
 */
public class Test {

    public static void main(String[] args){
        Target target = new Target();
        TargetFastClass fastClass = new TargetFastClass();
        int index = fastClass.getIndex("targetMethod1()V");
        fastClass.invoke(index, target, null);
    }
}

/**
 * 模拟代理类 如:UserService$$EnhancerByCGLIB$$1552dfb0
 */
class Target{
    public void targetMethod1(){
        System.out.println("...targetMethod1...");
    }
    public void targetMethod2(){
        System.out.println("...targetMethod2...");
    }
}

/**
 * 模拟代理类FastClass 如:UserService$$EnhancerByCGLIB$$1552dfb0$$FastClassByCGLIB$$8d34995d
 */
class TargetFastClass{

    public Object invoke(int index, Object o, Object[] arg){
        Target t = (Target) o;
        switch(index){
        case 1:
            t.targetMethod1();
            return null;
        case 2:
            t.targetMethod2();
            return null;
        }
        return null;
    }
    
    public int getIndex(String signature){
        String var = signature.toString();
        switch(var.hashCode()){
        case -1709726090:
            return 1;
        case -1709696299:
            return 2;
        }
        return -1;
    }
}

上例中,TargetFastClass是Target的Fastclass,在TargetFastClass中有两个方法getIndex和invoke。在getIndex方法中对Target的每个方法建立索引,并根据入参(方法名+方法的描述符)来返回相应的索引。Invoke根据指定的索引,以arg为入参调用对象O的方法。这样就避免了反射调用,提高了效率。


总结

拙技蒙斧正,不胜雀跃。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值