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

  今天来介绍另一种更为强大的代理——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动态代理相对来说更加简单粗暴。

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

原文地址:https://www.cnblogs.com/mfrank/p/8150925.html

时间: 2024-08-28 11:04:36

【Java入门提高篇】Day12 Java代理——Cglib动态代理的相关文章

Atitit 代理CGLIB 动态代理 AspectJ静态代理区别

Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为代表 1 1.2. JDK动态代理是模拟接口实现的方式,cglib是模拟子类继承的方式1 1.3. CGLIB代理模式的缺点 在static和final方法上应用横切关注点也是无法做到的.2 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 

java 静态代理 JDK动态代理 Cglib动态代理

下面以一个简单的银行账户为例讲述讲述动态代理. 设计一个银行账户类,包含用户的账户余额,实现查询和更新余额功能 这个系统用了一段时间,有客户要求对账说账户余额给弄错了?因为上面没有存取款记录,最后银行不认账,客户收到了损失.银行为了避免这种现象再次发生,决定对这个系统进行修改,但是因为bankAccount太过复杂,希望在不修改bankAccount的情况下,增加日志功能. 静态代理 使用静态代理解决上面的问题. 银行要求所有模块都需要添加日志功能,这对苦逼的程序员来说真的是一个不小的工作量啊,

Java代理之(jdk静态代理/jdk动态代理/cglib动态代理/aop/aspectj)

一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法.如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱.所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户.而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品. 专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象

zbb20180930 代理模式 -静态代理-jdk动态代理-cglib动态代理

CGLIB与JDK动态代理区别 区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理.而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理. 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB

【Java入门提高篇】Day11 Java代理——JDK动态代理

今天来看看Java的另一种代理方式--JDK动态代理 我们之前所介绍的代理方式叫静态代理,也就是静态的生成代理对象,而动态代理则是在运行时创建代理对象.动态代理有更强大的拦截请求功能,因为可以获得类的运行时信息,可以根据运行时信息来获得更为强大的执(骚)行(操)力(作). 我们还是以上一个例子为例,这里的IStars接口和Stars类都不需要修改,只需要修改代理类. 创建JDK动态代理需要先实现InvocationHandler接口,并重写其中的invoke方法,具体步骤如下: 1. 创建一个类

JDK动态代理 cglib动态代理的深入理解

代理: 可以从社会分工来理解代理,我们每个人都有自己明确的社会分工,比如我的社会分工是程序员, 而代理商,也叫中介也是一种职业.因为社会分工的明确才能提高生产力! 举个栗子: 如果我想去香港买奶粉,那么我可以有两种选择,一种是自己抽时间自己去买奶粉,一种是委托给代购去买奶粉.如果自己去买,那么需要自己去办理通行证,去制定行程路线,去做购物攻略,一个人怕走丢还要约同伴.......等等各种让自己分心分神的事情,那么就生产力而言,如果我委托给代购,那么我能节省更多的时间.精力去做好自己的社会分工,更

【Java入门提高篇】Day10 Java代理——静态代理

今天要介绍的是一个Java中一个很重要的概念--代理. 什么是代理?联系生活想想看,代理似乎并不陌生,最形象的代表便是经纪人,明星一般都有经纪人,经纪人作为中间人,负责代理明星的相关事宜,比如说,有人要请明星去唱歌表演,一般不会直接跟明星联系,而是联系他的经纪人,他的经纪人来负责安排行程,而真正唱歌表演的还是明星本人,经纪人仅仅作为一个附加物存在. 在Java中,代理也是这样的概念,来看个栗子: 先来创建一个明星类Stars: public class Stars implements ISta

【Java入门提高篇】Day5 Java中的回调(二)

Java中有很多个Timer,常用的有两个Timer类,一个java.util包下的Timer,一个是javax.swing包下的Timer,两个Timer类都有用到回调机制.可以使用它在到达指定时间间隔后发出通知,例如程序中有一个时钟,就可以每秒请求发送一个通知,以便更新时间显示.那么怎样通知Timer去完成我们的任务呢?在其他语言中,可以提供一个函数名,然后定时器周期性的调用它,但Java使用的是面向对象编程的思想,将某个类的对象传递给定时器,然后定时器再调用这个对象的方法,由于对象能携带的

【Java入门提高篇】Day16 Java异常处理(上)

当当当当当当,各位看官,好久不见,甚是想念. 今天我们来聊聊Java里的一个小妖精,那就是异常. 什么是异常?什么是异常处理? 异常嘛,顾名思义就是不正常,(逃),是Java程序运行时,发生的预料之外的事情,它阻止了程序按照程序员的预期正常执行. 异常处理,应该说异常处理机制,就是专门用来制服这个小妖精的法宝.Java中的异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰. 简而言之,Java异常处理就是能让