Java动态代理

来源:互联网 发布:淘宝刷单群 编辑:程序博客网 时间:2024/05/22 10:58

1. 什么是代理


我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品。关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者”对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就相当于为厂家做了一次对客户群体的“过滤”。我们把微商代理和厂家进一步抽象,前者可抽象为代理类,后者可抽象为委托类(被代理类)。通过使用代理,通常有两个优点,并且能够分别与我们提到的微商代理的两个特点对应起来:


  • 优点一:可以隐藏委托类的实现;

  • 优点二:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。


2. 静态代理


若代理类在程序运行前就已经存在,那么这种代理方式被成为静态代理,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下,静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类。下面我们用Vendor类代表生产厂家,BusinessAgent类代表微商代理,来介绍下静态代理的简单实现,委托类和代理类都实现了Sell接口。静态类的实现包括:一个interface,两个实现该interface的class。如下:

Sell接口的定义如下:

package Delegation.staticDele;/** * Created by cxh on 17/3/26. * 微商和委托方的公共接口 */public interface Sell {    void sell();    void add();}

Vendor类的定义如下:

package Delegation.staticDele;/** * Created by cxh on 17/3/26. * 委托方实现接口方法 */public class Vender implements Sell{    @Override    public void sell(){        System.out.println("in sell  method");    }    @Override    public void add(){        System.out.println("in add  method");    }}

代理类BusinessAgent的定义如下:

package Delegation.staticDele;/** * Created by cxh on 17/3/26. * 代理类实现接口sell方法 */public class BusinessAgent implements Sell{    private Vender vender;    public BusinessAgent(Vender v){        this.vender=v;    }    @Override    public void sell(){        vender.sell();    }    @Override    public void add(){        vender.add();    }}

从BusinessAgent类的定义我们可以了解到,静态代理可以通过聚合来实现,让代理类持有一个委托类的引用即可。


下面我们考虑一下这个需求:给Vendor类增加一个过滤功能,只卖货给大学生。通过静态代理,我们无需修改Vendor类的代码就可以实现,只需在BusinessAgent类中的sell方法中添加一个判断即可如下所示:

public class BusinessAgent implements Sell {    ...    public void sell() {        if (isCollegeStudent()) {            vendor.sell();        }    }    ...}


这对应着我们上面提到的使用代理的第二个优点:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。静态代理的局限在于运行前必须编写好代理类,下面我们重点来介绍下运行时生成代理类的动态代理方式。

3. 什么是动态代理

代理类在程序运行时创建的代理方式被成为动态代理。也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。这么说比较抽象,下面我们结合一个实例来介绍一下动态代理的这个优势是怎么体现的。

4. 使用动态代理

在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口,注意这个接口是java提供给我们的,然后我们可以复写里面的方法。这个接口的源码定义如下:

public interface InvocationHandler {    Object invoke(Object proxy, Method method, Object[] args);}

从InvocationHandler这个名称我们就可以知道,实现了这个接口的中介类用做“调用处理器”。当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,代理类对象作为proxy参数传入,参数method标识了我们具体调用的是代理类的哪个方法,args为这个方法的参数。这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。因此我们只需在中介类的invoke方法实现中输出“before”,然后调用委托类的invoke方法,再输出“after”。下面我们来一步一步具体实现它。

动态代理包括了4个文件:1个sell接口;1个vender类,实现了sell接口的委托方;1个代理类DynamicProxy,实现了

java.lang.reflect.InvocationHandler接口的类;一个测试类MainTest。
4.1 sell接口代码如下:
package Delegation.dynamicDele;/** * Created by cxh on 17/3/26. * 委托方/代理 共同大家的接口 */public interface Sell {    void sell();    void add();}
4.2 vender类,委托方代码如下:
package Delegation.dynamicDele;/** * Created by cxh on 17/3/26. * 委托方,供应商 */public class Vender implements Sell {    public void sell(){        System.out.println("this is sell method");    }    public void add(){        System.out.println("this is add method");    }}
4.3 代理类DynamicProxy代码如下:
package Delegation.dynamicDele;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * Created by cxh on 17/3/26. * 中介类,调用处理器 */public class DynamicProxy implements InvocationHandler {    private Object obj;//obj为动态代理对象    public DynamicProxy(Object obje){this.obj=obje;}    //参数说明:object为代理方对象,method调用的代理方的方法,args为调用的代理方方法的参数    @Override    public Object invoke(Object object, Method method,Object[] args) throws Throwable{        System.out.println("before");        Object result=method.invoke(obj,args);        System.out.println("after");        return result;    }}
4.4  测试类MainTest代码如下:
package Delegation.dynamicDele;import java.lang.reflect.Proxy;/** * Created by cxh on 17/3/26. */public class MainTest {    public static void main(String[] args) {        //创建中介类实类        DynamicProxy dynamicProxy=new DynamicProxy(new Vender());        //获取代理类实例sell        //在下代码中,我们调用Proxy类的newProxyInstance方法来获取一个代理类实例。        //          这个代理类实现了我们指定的接口并且会把方法调用分发到指定的调用处理器。        Sell sell=(Sell)(Proxy.newProxyInstance(Sell.class.getClassLoader(),new Class[]{Sell.class}, dynamicProxy));        sell.add();        sell.sell();    }}
4.5  运行结果如下:
beforethis is add methodafterbeforethis is sell methodafterProcess finished with exit code 0

0 0
原创粉丝点击