JDK和CGLIB生成动态代理类的区别

简介:

 关于动态代理和静态代理

当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象。

按照代理对象的创建时期不同,可以分为两种:

静态代理:事先写好代理对象类,在程序发布前就已经存在了;

动态代理:应用程序发布后,通过动态创建代理对象。

静态代理其实就是一个典型的代理模式实现,在代理类中包装一个被代理对象,然后影响被代理对象的行为,比较简单,代码就不放了。

其中动态代理又可分为:JDK动态代理和CGLIB代理。

1.JDK动态代理

此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。

代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。

JDK动态代理只能针对实现了接口的类生成代理。

2.CGLIB代理

CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,

主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。

 

JDK动态代理和CGLIB代理生成的区别

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

PS:final 所修饰的数据具有“终态”的特征,表示“最终的”意思:

  • final 修饰的类不能被继承。
  • final 修饰的方法不能被子类重写。
  • final 修饰的变量(成员变量或局部变量)即成为常量,只能赋值一次。
  • final 修饰的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有 一次赋值的机会,而且只能在构造方法中显式赋值,然后才能使用。
  • final 修饰的局部变量可以只声明不赋值,然后再进行一次性的赋值。

参考代码

CGLIB: 

 
1
2
3
4
5
6
7
8
public  Object createProxyObject(Object obj) { 
     this .targetObject = obj; 
     Enhancer enhancer =  new  Enhancer(); 
     enhancer.setSuperclass(obj.getClass()); 
     enhancer.setCallback( this ); 
     Object proxyObj = enhancer.create(); 
     return  proxyObj; // 返回代理对象,返回的对象其实就是一个封装了“实现类”的代理类,是实现类的实例。 

  

JDK: 

1
2
3
4
5
public  Object newProxy(Object targetObject) { // 将目标对象传入进行代理 
     this .targetObject = targetObject;  <br>     //注意这个方法的参数,后面是类实现的接口
     return  Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
             targetObject.getClass().getInterfaces(),  this ); // 返回代理对象 
}
 

在代码中可以看到,在生成代理类时,传递的是实现类所实现的接口 targetObject.getClass().getInterfaces(),所以JDK只能对于接口进行做代理。如果换成类的话,则会抛java.lang.ClassCastException异常。 

在Spring的源码中,可以看到很多生成代理类的代码。

 

动态代理的应用

AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作

实现AOP的技术,主要分为两大类:

一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;

二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。

默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。

 


目录
相关文章
|
3月前
|
Java 数据安全/隐私保护
【面试问题】JDK 动态代理与 CGLIB 区别?
【1月更文挑战第27天】【面试问题】JDK 动态代理与 CGLIB 区别?
|
9月前
|
Java Maven
JDK动态代理和CGLIB动态代理的区别及实例
JDK动态代理和CGLIB动态代理的区别及实例
126 0
|
9月前
|
Java 索引 Spring
静态代理?动态代理?JDK动态代理和CGLIB包实现动态代理的区别
什么是静态代理?什么是动态代理?JDK动态代理和CGLIB包实现动态代理的区别
88 1
静态代理?动态代理?JDK动态代理和CGLIB包实现动态代理的区别
|
10月前
|
Java Spring
jdk 动态代理
jdk 动态代理
|
设计模式 Java 数据安全/隐私保护
剖析代理模式及Java两种动态代理(JDK动态代理和CGLIB动态代理)
本文详述了代理模式以及我们经常接触到的两种具体实现(JDK动态代理和CGLIB动态代理),为读者理解代理模式、JDK动态代理和CGLIB动态代理提供帮助
127 0
剖析代理模式及Java两种动态代理(JDK动态代理和CGLIB动态代理)
|
Java
JDK之动态代理(JDK与CGLIB)与静态代理
代理类在程序运行时创建的代理方式被称为动态代理 静态代理中,代理类是自己定义好的,在程序运行之前就已经编译完成。然而动态代理,代理类并不是在Java代码中定义的,而是运行时根据我们在Java代码中的指示动态生成的。相比较静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法,比如想要在每个代理方法前都加上一个处理方法,静态代理就需要在每个类内部加上这个方法
133 2
JDK之动态代理(JDK与CGLIB)与静态代理
|
Java API 数据库
Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理
Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理
Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理
|
JavaScript 前端开发 Java
JDK和cglib生成代理类
JDK和cglib生成代理类
|
设计模式 Java
【动态代理】—— JDK和cglib的动态代理
【动态代理】—— JDK和cglib的动态代理
110 0
【动态代理】—— JDK和cglib的动态代理
|
Java Spring
JDK 动态代理与 CGLIB 有哪些区别?
Jdk 动态代理利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用。InvokeHandler来处理。
763 0
JDK 动态代理与 CGLIB 有哪些区别?