JMockit/Mockito/PowerMockit/Robo

2020-08-31  本文已影响0人  普通的程序员

目录

概念学习

要学习几个框架的原理,首先必须了解以下几个概念
代理模式
静态代理
动态代理
CGLIB
ASM
ByteBuddy

代理模式/静态代理/动态代理

代理模式就不多说了
https://www.runoob.com/design-pattern/proxy-pattern.html

这里讲的静态代理,就是代理模式的最基本的一种实现方式,
在开发者编程的时候定义好接口interface,也写好 该接口的实现类proxy class(代理类),
这种就是叫静态代理。

动态代理的意思就是,这个interface已经定义好了,但是实现类,是在运行时,通过某种方式在内存里创建的。
通过java提供的
Proxy类,InvocationHandler接口等api完成动态生成。
底层实现是,通过指定的classLoader,利用反射,完成代理类proxy class的生成,具体怎么生成的可自行跟踪

关键代码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
return defineClass0(loader, proxyName,
                    proxyClassFile, 0, proxyClassFile.length);

参考链接
https://blog.csdn.net/riemann_/article/details/86777505

JDK动态代理之实现与原理

CGLIB/ASM

其实cglib跟以上的静态动态代理不同,cglib是一个库,后者是一个理念(具体实现是反射创建类),同理ASM也只是一个库,这里能放在一起比较,只是单纯从代理的角度去做比较。

cglib提供Enhance等api,将真实对象类的class文件加载进来,通过ASM修改字节码生成其子类,覆盖父类相应的方法(真正在修改字节码的是ASM库)

CGLIB和Java动态代理的区别

可以参考
https://zhuanlan.zhihu.com/p/35144462
看下cglib生成一个代理类的过程

参考链接
CGLIB动态代理实现与原理

Android ASM框架详解

mockito原理

一句话『java动态代理+byteBuddy生成字节码』

mock对象的创建主要是为了创建一个mock对象的代理类,使得代理类代理mock对象的所有方法(从源码设计中包含了私有方法,但是受私有方法封装性原因,该私有方法无法进行mock).

mock实例方法的场景利用了Java运行时多态的原理,通过重写父类的方法来修改某个方法的行为。具体细节:
mockito首先接受一个指定的class类型,采用java的动态代理逻辑,使用了ByteBuddy框架来生成该class类型的代理实例。(ByteBuddy这个框架,它并不需要编译器的帮助,而是直接生成class,然后使用ClassLoader来进行加载)

代理对象继承了被mock类,为了对每个方法做拦截,通过byte buddy设置拦截器 MockMethodInterceptor。MockMethodInterceptor的主要作用是将mock对象的拦截方法执行交给了MockHandler来处理。

具体代码跟踪
https://albenw.github.io/posts/9758301d/

后续的关键点就在这个ByteBuddy工具怎么生成动态类对象了。

PowerMockito原理

动态代理+ javassist修改字节码+ objenesis绕过构造方法来实例化对象

PowerMockito比Mockito强大的地方在

参考链接
https://www.cnblogs.com/zjdxr-up/p/11571207.html

Robolectric 原理

ASM 修改字节码 + classLoader替换
https://www.jianshu.com/p/0848a47d37ab

JMockit原理

先使用asm修改原有class的字节码, 再利用jdk的instrument机制替换现有class的内容(使用的工具是agent)
从而达到mock的目的。

整个mock过程看
参考链接
https://zhuanlan.zhihu.com/p/106882864

对比

一个十年前的提问
https://stackoverflow.com/questions/4105592/comparison-between-mockito-vs-jmockit-why-is-mockito-voted-better-than-jmockit

版本都与现在不一样了。
按高票的意思是,JMockit更加灵活。

上一篇下一篇

猜你喜欢

热点阅读