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

来源:互联网 发布:mac涂层脱落可以换吗 编辑:程序博客网 时间:2024/05/20 07:13

 关于动态代理和静态代理

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

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

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

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

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

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

1.JDK动态代理

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

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

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

2.CGLIB代理

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

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

 

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

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

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异常。 


0 0
原创粉丝点击