类型 | 机制 | 回调方式 | 使用场景 | 效率 |
jdk动态代理 | 代理类和目标类都实现了同样的接口,InvocationHandler持有目标类,代理类委托InvocationHandler去调用目标类的原始方法 | 反射 | 目标类是接口类,适用于需重复创建对象(非单例) | 效率瓶颈在反射调用稍慢,创建类速度快 |
cglib动态代理 | 继承机制,代理类继承了目标类并重写了目标方法,通过回调函数MethodInterceptor调用父类方法执行原始逻辑 | 通过FastClass方法索引调用 | 可以是接口也可以是具体类,非final类,非final方法。适用于无需重复创建对象(单例) | 第一次调用因为要生成多个Class对象较JDK方式慢(创建类慢),多次调用因为有方法索引较反射方式快,如果方法过多switch case过多其效率会降低 |
上篇文章讲了两种cglib实现方式,在相同的情况下invokeSuper + setSuperClass 永远比 invoke + setInterfaces慢,因为invokeSuper + setSuperClass方式生成的FastClass类更大,switch case 更多
cglib invoke + setInterfaces 在方法数量较少的时候,在函数平均调用的情况下 比jdkProxy快,随着函数增多,优势越来越不明显,到达某个数量级一定比jdk动态代理慢,因为毕竟jdkProxy是反射调用
cglib invoke + setInterfaces 在调用特定函数(在switch中靠后的case) 会比jdk动态代理慢
结论:
从 jdk6 到 jdk7、jdk8 ,动态代理的性能得到了显著的提升,而 cglib 的表现并未跟上,甚至可能会略微下降。传言的 cglib 比 jdk动态代理高出 10 倍的情况也许是出现在更低版本的 jdk 上吧。