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:
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:
public Object newProxy(Object targetObject) {// 将目标对象传入进行代理
this.targetObject = targetObject;
//注意这个方法的参数,后面是类实现的接口
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"/>)。
JDK和CGLIB生成动态代理类的区别的更多相关文章
- 【4】JDK和CGLIB生成动态代理类的区别
当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代理:事先写好代理对象类,在 ...
- JDK和CGLIB生成动态代理类的区别(转)
关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...
- CGLIB 和 JDK生成动态代理类的区别(转)
文章转自http://luyuanliang.iteye.com/blog/1137292 AOP 使用的设计模式就是代理模式,是对IOC设计的补充.为了扩展性,往往会加上反射,动态生成字节码,生成代 ...
- JDK 和 CGLib 实现动态代理和区别
JDK 和 CGLib 实现动态代理和区别 在日常的开发中,Spring AOP 是一个非常常用的功能.谈到 AOP,自然离不开动态代理. 那么,基于 JDK 和 CGLib 如何实现动态代理,他们之 ...
- JDK和Cglib实现动态代理实例及优缺点分析
Spring AOP使用的核心技术是动态代理,说到动态代理就不得不和设计模式中的代理模式联系起来,通过代理模式我们可以对目标类进行功能增强,在某个方法的执行前后增加一些操作,例如计算方法执行效率.打印 ...
- jdk与cglib的动态代理
JDK动态代理中包含一个类和一个接口: InvocationHandler接口: public interface InvocationHandler { public Object invoke(O ...
- cgLib生成动态代理
package com.stono.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import ...
- java面试题之spring aop中jdk和cglib哪个动态代理的性能更好?
在jdk6和jdk7的时候,jdk比cglib要慢: 在jdk8的时候,jdk性能得到提升比cglib要快很多: 结论出自:https://www.cnblogs.com/xuliugen/p/104 ...
- Alibaba Java诊断工具Arthas查看Dubbo动态代理类
原创/朱季谦 阅读Dubbo源码过程中,会发现,Dubbo消费端在做远程调用时,默认通过 Javassist 框架为服务接口生成动态代理类,接着再去调用代理类实现远程接口调用.在阅读这部分源码时,最后 ...
随机推荐
- vue常用UI组件
Mint UI 项目主页:http://mint-ui.github.io/#!/zh-cn demo:http://elemefe.github.io/mint-ui/#/ github地址:htt ...
- js计算数字长度
js调用toString方法转为字符串后取长度 var num = 123; alert(num.toString().length);
- OpenCV入门(2)- Java第一个程序
1.下载和安装OpenVC环境 从官方连接 https://opencv.org/releases.html 下载Windows的安装包 下载下来的就是一个压缩包,安装解压后,对Java开发有效的目录 ...
- [C++]线性链表之顺序表<二>
/* @content 线性链表之顺序表 @date 2017-3-21 1:06 @author Johnny Zen */ /* 线性表 顺序表 链式表[带头指针/不 ...
- R 的农场 chebnear (二分答案+最近平面点对)
题面 \(solution:\) 这道题想到二分答案应该是不难的,因为题目是求平均工资的最小值,这个显然具备单调性: 我们设平均工资的最小值为ans,如果我们现在的平均工资x小于ans那么将x带入题目 ...
- C++ vector 使用笔记
map 插入 vector #include <string> #include <iostream> #include <algorithm> #include ...
- POI读取Excel(xls、xlsx均可以)——(四)
maven构建的项目-->pom.xml文件 eclipse提供Dependencies直接添加依赖jar包的工具:直接搜索poi以及poi-ooxml即可,maven会自动依赖需要的jar包: ...
- 没有备份怎么恢复被drop的表(利用undrop-for-innodb)
介绍: 也许大家都难以理解,这么重要的数据为啥不备份(或者备份不可用)?而且还任性的drop table了.显然有备份是最好的,但是它们并不总是可用的.这种情况令人恐惧,但并非毫无希望.在许多 ...
- Python3学习笔记25-logging模块
logging模块,Python自带用来记录日志的模块. 因为工作需要用到关于日志的,最近一直都在看关于日志模块的东西,百度了很多文章,可惜都是看的让人一头雾水,最后运气不错,找到一篇很详细的文章.传 ...
- java linux ftp问题
java写的ftp上传类,本地测试环境可以用,阿里云服务器不可用,两者系统均为centos.经过测试,发现appche的ftpclient类不可用,换成sun的ftpclient可以使用.