在上一篇文章中说到动态代理的实现除了JDK还有第三方的实现。现在就来瞧瞧JDK之外的动态代理的实现。
Cglib
这个库在Github上有1390颗星星,下面是对Cglib的描述。
cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.
说到使用这个库的框架,其中大名鼎鼎的Hibernate就用到了,当然还有Spring。 Spring的AOP默认使用JDKProxy,如果被代理的类没有实现接口就使用Cglib去生成动态代理类。
它的出现是为了弥补JDK动态代理中不能对未实现接口的类进行代理。其原理也可想而知了,无非就是动态生成一个子类,这个子类继承了要代理的类,然后去重写父类(需要代理的类)的方法。这样的话,代理类就一定不能是final类型了,需要代理的方法也不能是final。因为Java不允许继承final类,不允许重写final方法。
下面通过一个实例来介绍Cglib实现动态代理。
|
|
|
|
|
|
从表面上来看和JDK的使用还是有类似的地方的。Cglib使用Enhancer
来去装载父类,将方法拦截器植入到生成的子类字节码中,最后创建对象。Cgilb依赖ASM字节码框架去动态生成字节码,具体生成出来的字节码文件和JDK动态代理生成出来的差别很大,区别就在于Cglib生成的代理类没有使用反射去调用要被代理的方法。从这里就可以看出Cglib在执行效率上要比JDK动态代理要高,毕竟反射效率是很低的。
Byte Buddy
这个类库是最近看一个RPC框架代码的时候发现的。起因是自己想尝试着写一个简单的远程方法调用的样例程序,在Github上找到了一个简单的基于Netty的实现,其中在处理动态代理的时候除了使用JDK的实现还有一个额外的实现,那就是Byte Buddy。然后稍微研究了一番,发现使用这个类库写动态代理确实很方便。
废话不多讲,先简单的看代码实现。
|
|
|
|
|
|
|
|
这只是一个很简单的小栗子,还有很多复杂的特性没有深入研究。我只能对写这个库的作者表示很崇高的敬佩!
小结
当然除了文章中所介绍的生成动态代理的工具还有很多没有提及,比方说javaassit等。其原理大致类似,无非就是在JVM加载字节码的时候将字节码给替换了或者改掉了,很多都依赖于ASM库,如果对class字节码规范很熟悉的话自己也可以使用ASM来写一个字节码生成工具。
从阅读别人写的RPC框架的源码中发现了很多有意思的东西,从其中的动态代理可以了解到字节码生成加载。慢慢才发现写代码真的不是想象中那么简单的,变化的东西太多了,也只有时刻保持着学习的态度也才可能跟得上节奏,才不会被淘汰。