【Java入门提高篇】Day12 Java代理——Cglib动态代理

前端之家收集整理的这篇文章主要介绍了【Java入门提高篇】Day12 Java代理——Cglib动态代理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

  什么是Cglib动态代理?

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

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

  先定义一个Programmer类:

public class Programmer {

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

  然后定义一个代理类:

class ProgrammerProxy implements MethodInterceptor {

    /**
     * 内部持有委托类对象的引用
     */
     Object target;

    
     * 创建代理类对象
     public Programmer createProxy(Programmer object){
        target = object;
        //创建Enhancer对象
        Enhancer enhancer = new Enhancer();
        设置要代理的目标类,以扩展功能
        enhancer.setSuperclass(this.target.getClass());
        设置单一回调对象,在回调中拦截对目标方法调用
        enhancer.setCallback();
        设置类加载器
        enhancer.setClassLoader(object.getClass().getClassLoader());
        创建代理对象
        return (Programmer)enhancer.create();
    }

    
     * 回调方法:在代理实例上拦截并处理目标方法调用,返回结果
     * @param proxy  代理类
     *  method 被代理的方法
     *  params 该方法的参数数组
     *  methodProxy
     */
    @Override
    public Object intercept(Object proxy,Method method,Object[] params,MethodProxy methodProxy) throws Throwable {
        调用之前处理
        doBefore();

        调用方法
        method.invoke(target,params);

        调用之后处理
        doAfter();

        return null;
    }

    private  doAfter() {
        System.out.println("do after.");
    }

     doBefore() {
        System.out.println("do before.");
    }

}

  然后测试一下:

 ProxyTest {

    @Test
     testCglibProxy(){
        创建一个Programmer对象
        Programmer programmerA =  Programmer();
        programmerA.setName("Frank");

        创建代理对象
        Programmer programmerProxyA =  ProgrammerProxy().createProxy(programmerA);
        programmerProxyA.code();

        修改代理对象
        programmerProxyA.setName("Wang");
        programmerProxyA.code();

        修改委托类对象
        programmerA.setName("Song");
        programmerProxyA.code();
    }
}

  输出如下:

Setting Name.
do before.
Frank is writing bugs.
 after.
 before.
Setting Name.
 before.
Wang is writing bugs.
 after.
Setting Name.
 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包下载地址:http://download.csdn.net/download/qiuyingjia/10181844

猜你在找的Java相关文章