JDK动态代理与CGLib的区别(5大核心区别)

JDK动态代理与CGLib的区别(5大核心区别)-mikechen

动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询、RPC等,Java中两种常见的动态代理方式有:JDK原生动态代理和CGLIB动态代理。

下面我们就来谈谈两者的区别。

JDK动态代理

Java 提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了 Spring 的很多地方。

JDK 动态代理主要涉及 java.lang.reflect 包下边的两个类:Proxy 和 InvocationHandler。其中,InvocationHandler 是一个接口,可以通过实现该接口定义横切逻辑(如:我们在方法执行前后打印的日志,本文只是为了演示,实际的应用一般不会只是简单的打印日志的),并通过反射机制调用目标类的代码,动态地将横切逻辑和业务逻辑编织在一起。

JDK 动态代理是不需要第三方库支持,只需要 JDK 环境就可以进行代理,使用条件

  • 业务目标对象实现接口
  • 实现 InvocationHandler 接口
  • 使用 Proxy.newProxyInstance() 方法生成代理对象

JDK 动态代理的话,它有一个限制,就是它只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,如何创建动态代理实例哪?答案就是 CGLib。

 

CGLib动态代理

CGLIB是一个功能强大,高性能的代码生成包,它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。

静态代理和 JDK 动态代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理。

Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口,它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截

在 AOP 编程中如何选择代理模式

  • 目标对象需要实现接口,用 JDK 代理
  • 目标对象不需要实现接口,用 Cglib 代理

通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

 

CGLib与JDK动态代理的区别

1.实现的区别

JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

CGLib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

 

2.使用的区别

JDK 动态代理只能针对接口实现类生成代理实例,而不能针对类,也就是说它是面向接口的;

CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,并覆盖其中方法实现增强,CGLIB 因为采用的是继承,所以该类或方法最好不要声明成 final,对于 final 类或方法,是无法继承的;

 

3.性能的区别

CGLib所创建的动态代理对象在实际运行时候的性能要比JDK动态代理高不少;

但是CGLib在创建对象的时候所花费的时间却比JDK动态代理要多很多;

 

4.创建的区别

对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用CGLib动态代理,反正,则比较适用JDK动态代理。

 

3.Spring选择区别

Bean实现接口,选用JDK

Bean没有实现接口,选用CGLIB

 

 

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法