Spring 高级 cglib代理原理 MethodProxy 总结
总结
- 当调用 MethodProxy 的 invoke 或 invokeSuper 方法时, 会动态生成两个类
- ProxyFastClass 配合代理对象一起使用, 避免反射
- TargetFastClass 配合目标对象一起使用, 避免反射 (Spring 用的这种)
- TargetFastClass 记录了 Target 中方法与编号的对应关系
- save(long) 编号 2
- save(int) 编号 1
- save() 编号 0
- 首先根据方法名和参数个数、类型, 用 switch 和 if 找到这些方法编号
- 然后再根据编号去调用目标方法, 又用了一大堆 switch 和 if, 但避免了反射
- ProxyFastClass 记录了 Proxy 中方法与编号的对应关系,不过 Proxy 额外提供了下面几个方法
- saveSuper(long) 编号 2,不增强,仅是调用 super.save(long)
- saveSuper(int) 编号 1,不增强, 仅是调用 super.save(int)
- saveSuper() 编号 0,不增强, 仅是调用 super.save()
- 查找方式与 TargetFastClass 类似
- 为什么有这么麻烦的一套东西呢?
- 避免反射, 提高性能, 代价是一个代理类配两个 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}); } }