Spring 高级 cglib代理原理 MethodProxy 总结

总结

  1. 当调用 MethodProxy 的 invoke 或 invokeSuper 方法时, 会动态生成两个类
    • ProxyFastClass 配合代理对象一起使用, 避免反射
    • TargetFastClass 配合目标对象一起使用, 避免反射 (Spring 用的这种)
  1. TargetFastClass 记录了 Target 中方法与编号的对应关系
    • save(long) 编号 2
    • save(int) 编号 1
    • save() 编号 0
    • 首先根据方法名和参数个数、类型, 用 switch 和 if 找到这些方法编号
    • 然后再根据编号去调用目标方法, 又用了一大堆 switch 和 if, 但避免了反射
  1. ProxyFastClass 记录了 Proxy 中方法与编号的对应关系,不过 Proxy 额外提供了下面几个方法
    • saveSuper(long) 编号 2,不增强,仅是调用 super.save(long)
    • saveSuper(int) 编号 1,不增强, 仅是调用 super.save(int)
    • saveSuper() 编号 0,不增强, 仅是调用 super.save()
    • 查找方式与 TargetFastClass 类似
  1. 为什么有这么麻烦的一套东西呢?
    • 避免反射, 提高性能, 代价是一个代理类配两个 FastClass 类, 代理类中还得增加仅调用 super 的一堆方法
    • 用编号处理方法对应关系比较省内存, 另外, 最初获得方法顺序是不确定的, 这个过程没法固定死
package com.mangoubiubiu.show.a14;

import org.springframework.cglib.core.Signature;

public class ProxyFastClass {



    static Signature s0 = new Signature("saveSuper","()V");
    static  Signature s1 = new Signature("saveSuper","(I)V");
    static  Signature s2 = new Signature("saveSuper","(J)V");

    //获取代理方法的编号

    /**
     * Target
     *    save()
     *    save(int)
     *    save(long)
     *    根据方法的签名信息获取编号
     * @param signature 方法的名字 参数 返回值
     * @return
     */


    public int getIndex(Signature signature){
        if(s0.equals(signature)){
            return 0;
        }else if(s1.equals(signature)){
            return 1;
        }else if(s2.equals(signature)) {
            return 2;
        }
        return  -1;
    }



    public Object invoke(int index,Object target,Object[] args){

        if(index == 0){
            ((Proxy)target).saveSuper();
            return null;
        }else if(index == 1){
            ((Proxy)target).saveSuper((int)args[0]);
            return null;

        }else if(index == 2){
            ((Proxy)target).saveSuper((long)args[0]);
            return null;

        }else {
            throw  new RuntimeException("无此方法");
        }

    }


    public static void main(String[] args) {
        ProxyFastClass fastClass = new ProxyFastClass();
        int index = fastClass.getIndex(new Signature("saveSuper", "(I)V"));
        System.out.println(index);
        fastClass.invoke(index,new Proxy(),new Object[]{100});


    }




}
package com.mangoubiubiu.show.a14;
import org.springframework.cglib.core.Signature;

public class TargetFastClass {

    static  Signature s0 = new Signature("save","()V");
    static  Signature s1 = new Signature("save","(I)V");
    static  Signature s2 = new Signature("save","(J)V");

    //获取目标方法的编号

    /**
     * Target
     *    save()
     *    save(int)
     *    save(long)
     *    根据方法的签名信息获取编号
     * @param signature 方法的名字 参数 返回值
     * @return
     */


    public int getIndex(Signature signature){
        if(s0.equals(signature)){
            return 0;
        }else if(s1.equals(signature)){
            return 1;
        }else if(s2.equals(signature)) {
            return 2;
        }
        return  -1;
    }



    public Object invoke(int index,Object target,Object[] args){

        if(index == 0){
            ((Target)target).save();
            return null;
        }else if(index == 1){
            ((Target)target).save((int)args[0]);
            return null;

        }else if(index == 2){
            ((Target)target).save((long)args[0]);
            return null;

        }else {
            throw  new RuntimeException("无此方法");
        }

    }


    public static void main(String[] args) {
        TargetFastClass fastClass = new TargetFastClass();
        int index = fastClass.getIndex(new Signature("save", "(I)V"));
        System.out.println(index);
        fastClass.invoke(index,new Target(),new Object[]{100});


    }


}

 

posted @ 2022-10-02 15:47  KwFruit  阅读(471)  评论(0编辑  收藏  举报