您的位置:首页技术文章
文章详情页

详解Java Cglib动态代理

浏览:6日期:2022-08-26 18:13:39

今天来介绍另一种更为强大的代理——Cglib动态代理。

什么是Cglib动态代理?

我们先回顾一下上一篇的jdk动态代理,jdk动态代理是通过接口来在运行时动态创建委托类的代理对象,但是跟静态代理一样有一个缺点,就是必须和委托类实现相同的接口,当接口数量增加时,便需要增加代理类的数量才能满足需求,而且如果委托类是别人写的,而且没有实现任何接口,那么jdk动态代理就有些力不从心了。

这时候Cglib动态代理就脱颖而出了,Cglib并不依赖接口,可以直接生成委托类的代理对象,而且可以代理委托类的任意非final修饰的public和protected方法,我们可以先来看一个栗子。

先定义一个Programmer类:

public class Programmer { private String name; public void setName(String name) { System.out.println('Setting Name.'); this.name = name; }public void code(){ System.out.println(name + ' is writing bugs.'); }}

然后定义一个代理类:

public class ProgrammerProxy implements MethodInterceptor { /** * 内部持有委托类对象的引用 */ private Object target; /** * 创建代理类对象 */ public Programmer createProxy(Programmer object){ target = object; //创建Enhancer对象 Enhancer enhancer = new Enhancer(); //设置要代理的目标类,以扩展功能 enhancer.setSuperclass(this.target.getClass()); //设置单一回调对象,在回调中拦截对目标方法的调用 enhancer.setCallback(this); //设置类加载器 enhancer.setClassLoader(object.getClass().getClassLoader()); //创建代理对象 return (Programmer)enhancer.create(); } /** * 回调方法:在代理实例上拦截并处理目标方法的调用,返回结果 * @param proxy 代理类 * @param method 被代理的方法 * @param params 该方法的参数数组 * @param methodProxy */ @Override public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable { //调用之前处理 doBefore(); //调用原方法 method.invoke(target,params); //调用之后处理 doAfter(); return null; } private void doAfter() { System.out.println('do after.'); } private void doBefore() { System.out.println('do before.'); }}

然后测试一下:

public class ProxyTest { @Test public void testCglibProxy(){ //创建一个Programmer对象 Programmer programmerA = new Programmer(); programmerA.setName('Frank'); //创建代理对象 Programmer programmerProxyA = new ProgrammerProxy().createProxy(programmerA); programmerProxyA.code(); //修改代理对象 programmerProxyA.setName('Wang'); programmerProxyA.code(); //修改委托类对象 programmerA.setName('Song'); programmerProxyA.code(); }}

输出如下:

Setting Name.do before.Frank is writing bugs.do after.do before.Setting Name.do after.do before.Wang is writing bugs.do after.Setting Name.do before.Song is writing bugs.do after.

Cglib实现动态代理的步骤也不是很麻烦,先创建一个类实现MethodInterceptor接口,重写intercept方法,在intercep中可以截获委托类的所有非final修饰的public和protected方法,上例中,method.invoke(target,params);即为调用原对象的原方法,在代理类中保存了委托类对象的引用,这一点跟JDK动态代理是一样的。在调用原方法前先调用了doBefore方法,调用之后还调用了doAfter方法,从而实现了代理功能。至于createProxy方法,也只是一个固定步骤,先创建Enhance对象,然后将委托类的一些属性往里塞,然后调用create方法来动态生成代理对象。

在测试类中,为了更明显的说明代理类与委托类的关系,分别用代理类对象programmerProxyA和委托类对象programmerA对name字段进行修改,可以产生一样的效果。

下面来对比一下Cglib动态代理与JDK动态代理:

1.两者都是动态代理,都是运行时动态生成代理对象。

2.JDK动态代理利用的是接口信息来实现的代理,委托类必须实现某个或者某些接口,而Cglib则是利用继承关系,利用asm在运行时动态生成委托类的子类,从而实现对委托类的代理。因此不依赖接口。

3.Cglib由于是利用继承关系来实现代理的,因此无法代理被final修饰的类以及被final修饰的方法。

4.Cglib一般来说效率要比JDK动态代理效率更高,可以实现的代理也更为强大。

当然,具体情况具体分析,虽然Cglib比Jdk动态代理更强大,但并不一定各个地方都强行使用,有时候JDK动态代理相对来说更加简单粗暴。

至此,本篇完结,代理相关内容讲解完毕,欢迎大家继续关注。

jar包下载地址:https://www.jb51.net/softs/570453.html

以上就是详解Java Cglib动态代理的详细内容,更多关于Java Cglib动态代理的资料请关注好吧啦网其它相关文章!

标签: Java
相关文章: