类型

机制

回调方式

使用场景

效率

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 上吧。