接上文:4.2Java设计模式-----JDK动态代理(Dynamic Proxy)

Cglib动态代理

百度百科:Cglib是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。

Cglib动态代理,是JDK静态代理,JDK动态代理之后的另一种代理方式。通过名称我们可以发现,JDK静态代理和JDK动态代理都是由Java官方提供的代理方式;而Cglib动态代理则是第三方的开源项目。在使用时,我们需要引入第三方jar包来实现

为什么会有Cglib动态代理

虽然JDK动态代理解决了JDK静态代理的一些缺点,但是JDK动态代理也还是存在一些缺点的。诸如:JDK动态代理必须要求代理类实现某个接口类,照这种情况,那么我们普通的类就无法使用动态代理了。按照JDK动态代理实现方法来看,是这么一回事,这明显就是JDK动态代理的缺点,所以Cglib动态代理也就应运而生了

JDK动态代理为什么必须要求代理类实现接口?

因为JDK的动态代理,是通过接口来进行强制转换的。通过代理生成的代理对象,可以强制转换为接口类型,就可以直接调用该类的相关方法来完成一系列的操作

Cglib动态代理的优点

①相比JDK动态代理,我们可以省去声明接口类的这个步骤,可以解除JDK动态代理的限制

②性能方面:JDK低版本的情况下,Cglib动态代理性能明显高于JDK动态代理,有说快10倍以上,可能出现在更低的JDK版本上吧。随着JDK版本的升级,JDK7以后,JDK动态代理也做出了很大的优化,性能好像已经超出了Cglib动态代理。有网友测试:在运行次数较少(1,000,000)的情况下,jdk动态代理比 cglib 快了差不多30%;而当调用次数增加之后(50,000,000), 动态代理比 cglib 快了接近1倍。(数据来自网络,我没有做测试)

Cglib动态代理的原理

Cglib的动态代理,就是子类继承父类。即:通过生成一个被代理对象的子类,然后重写父类的方法生成以后的对象,所以目标类和方法不能声明为final类型。可以强制转化为被代理对象(也就是自己写的类) 。即:将子类的引用赋值给父类

Cglib动态代理代码实现

①因为是三方开源项目,我们需要先引入相应Jar包,此处通过Maven导入依赖

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.12</version>
</dependency>

②先来一个被代理类对象,此处用到的Student被代理类同前文中JDK动态代理保持不变(Cglib动态代理,Person接口不需要了)

/*** 被代理类对象*/
public class Student {public void findHouse(){System.out.println("被代理人需求:我是学生A,我现在想找一个10平米的小房间,用来学习");}
}

③来声明一个代理类对象CglibProxy

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;//使用Cglib,需要实现MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {//getInstance方法,同JDK动态代理、静态代理一样,都是为了获取到被代理对象的引用public Object getInstance(Class clazz){//Enhancer是一个非常重要的类,它允许为非接口类型创建一个JAVA代理,Enhancer动态的创建给定类的子类并且拦截代理类的所有的方法,和JDK动态代理不一样的是不管是接口还是类它都能正常工作。Enhancer enhancer = new Enhancer();//把父类设置为谁?这一步就是告诉Cglib,生成的子类要继承哪个类enhancer.setSuperclass(clazz);//设置回调,使生成的代理类对象在每调用被代理类方法时,都去调用下面的intercept方法enhancer.setCallback(this);//enhancer.create()的工作:1.生成源代码   2.编译成class文件   3.加载到JVM中,生成并返回被代理对象......等等return enhancer.create();}@Overridepublic Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("我是中介,我代理的用户需要租一间房屋,如下是用户的一些需求");System.out.println("-----------------------------------------------------");//这里有个疑问:代理是需要获取到被代理对象的引用,但是Cglib好像并没有获取被代理对象的引用。那怎么还能用代理呢?//其实这里这个object的引用,是由Cglib帮我们new出来的//Cglib new出来的对象,是被代理对象的子类(继承了我们自己写的那个被代理类)//面向对象编程(OOP)中,在new 子类之前,实际上是默认调用了super()方法的//也就是说,new了子类的同时,也必须先new出来父类。这就相当于是间接的持有了我们父类的引用//实际上就是:子类重写了父类的所有方法//我们改变子类对象的某些属性,是可以间接的操作父类的属性的//是这样子的,代理便可以通过new子类的形式,间接获取到我们被代理对象的引用了methodProxy.invokeSuper(object,args);System.out.println("-----------------------------------------------------");System.out.println("我是中介,如上就是我代理用户的需求");return null;}
}

对代码进行的一些简单解释,请看代码中备注

④来一个测试类

/*** 测试类*/
public class test {public static void main(String[] args) {//生成的代理类的class文件到指定路径//System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定要保存class文件的路径");Student student = (Student)new CglibProxy().getInstance(Student.class);System.out.println(student.getClass());student.findHouse();}
}

⑤代码运行结果

我是中介,我代理的用户需要租一间房屋,如下是用户的一些需求
-----------------------------------------------------
被代理人需求:我是学生A,我现在想找一个10平米的小房间,用来学习
-----------------------------------------------------
我是中介,如上就是我代理用户的需求

如何查看生成的代理类的class文件

//在测试类中,添加如下代码,则会将class文件生成到指定路径
//如若需要查看class文件,可以通过反编译工具来查看
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定要保存class文件的路径");

Cglib动态代理与JDK动态代理的区别

①JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象(方式不同:一个是实现,一个是继承)

②JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。

③JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。

至此,JDK静态代理,JDK动态代理,Cglib动态代理到此就告一段落了。

附链接:4. Java设计模式-----代理模式(Proxy Pattern)

4.1 Java设计模式-----JDK静态代理(Static Proxy)

4.2 Java设计模式-----JDK动态代理(Dynamic Proxy)

Java设计模式-----Cglib动态代理(Cglib Proxy)相关推荐

  1. 【java设计模式】之 代理(Proxy)模式

    代理模式的核心作用就是通过代理,控制对对象的访问.这跟实际中是一样的,比如说明星都有经纪人,这就是一个代理,比如有人要找某明星拍戏,那么首先处理这事的是他的经纪人,虽然拍戏需要自己拍,但是拍戏前后的一 ...

  2. 深入理解Java Proxy和CGLIB动态代理原理

    点击上方关注,每天进步一点点 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译 ...

  3. Java Proxy和CGLIB动态代理原理

    动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...

  4. Java动态代理、CGLIB动态代理

    文章目录 代理模式 静态代理 动态代理 CGLIB动态代理 JDK动态代理源码分析 代理模式 代理模式是常见的设计模式之一,Java我们通常通过new一个对象然后调用其对应的方法来访问我们需要的服务. ...

  5. Java中的原生动态代理和CGLIB动态代理的原理,我不信你全知道!

    作者:CarpenterLee cnblogs.com/CarpenterLee/p/8241042.html 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询 ...

  6. 【Spring6】| GoF之代理模式(JDK动态代理和CGLIB动态代理)

    目录 一:GoF之代理模式 1. 对代理模式的理解 2. 静态代理 3. 动态代理 3.1 JDK动态代理 3.2 CGLIB动态代理 一:GoF之代理模式 1. 对代理模式的理解 生活场景1:牛村的 ...

  7. 你必须会的 JDK 动态代理和 CGLIB 动态代理

    来自:ytao 我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性.通过从静态代理.JDK 动态代理.CGLIB 动 ...

  8. SpringAOP的CGLIB动态代理的底层原理实现

    欢迎加入java学习讨论群:725562382 CGLIB动态代理: CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以 ...

  9. cglib动态代理jar包_Java中的原生动态代理和CGLIB动态代理的原理,我不信你全知道!...

    作者:CarpenterLee cnblogs.com/CarpenterLee/p/8241042.html 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询 ...

最新文章

  1. MyBatis简介——半自动的持久化层框架(SQL映射框架)|| 支持定制化sql
  2. Exchanging Partitions and Subpartitions with Tables--官方文档
  3. c# winform 打包(带数据库安装)
  4. 前端学习(1948)vue之电商管理系统电商系统之排序
  5. 拼接图像亮度均匀调整_品质不变 价格更香 | 爆款拼接屏新品上市
  6. 数学建模 聚类模型
  7. 【BZOJ5249】【九省联考2018】—IIIDX(线段树)
  8. 权限提升 bypass
  9. robots.txt详解
  10. linux gt240驱动下载,NV显卡Linux驱动195.36.08版发布
  11. c++内存池作用和优势
  12. 《遥远的救世主》遵守客观规律(三)——文化属性
  13. ubuntu 下的pdfcrop功能不(pdf剪切)
  14. Ramnit 蠕虫分析
  15. 智能温度、电压监测系统
  16. MySQL--DQL
  17. (论文笔记07.Survivalism: Systematic Analysis of Windows Malware Living-Off-The-Land(CCF A)2021)
  18. 【Airtest更新】AirtestIDE更新至1.2.10;Airtest更新至1.2.0
  19. NBA球星信息查询 需求描述 以下是一段包括球员信息的文本,要求编写一个程序,让用户能按照自己喜欢的球队查询其所有球员信 息,并格式化打印出来。 “Carmelo Anthony,Portland
  20. 苹果CMS采集资源后不显示图片

热门文章

  1. 【idea中Activiti BPMN visualizer插件和Camunda Modeler工作流设计器的简单使用】
  2. 蔬菜大棚成本_蔬菜大棚的类型及建造成本 不得不看
  3. ios safari 描述文件 跳转到_IOS APP与APP和APP与Safari间的跳转
  4. java 汇编语言_Java是汇编语言么
  5. win7 docker centos安装mysql_win7下docker环境centos容器中安装mysql5.7
  6. -如何调整html页面的间距,css中字间距怎么设置?
  7. Simscape动力学仿真驱动关节添加信号
  8. MongoDB 面试题及答案
  9. Redis操作相关命令:查看、停止、启动
  10. Nginx深入详解之upstream分配方式