• Java动态代理


    这周看RPC相关的代码时,里面用到了动态代理的相关知识,以前没怎么接触过,因此学习了下。

    一、代理

    代理是一种基本的设计模式,它是为了提供额外或者不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与实际对象的通信,

    因此代理通常充当着中间人的角色,下面我们来看一个展示代理结构的简单例子:

    public interface Interface {
    void doSomething();
    void somethingElse(String arg);
    }

    public class RealObject implements Interface{
    @Override
    public void doSomething() {
    System.out.println("doSomething");
    }

    @Override
    public void somethingElse(String arg) {
    System.out.println("somethingElse:"+arg);
    }
    }

    public class SimpleProxy implements Interface {
    private Interface proxied;
    public SimpleProxy(Interface proxied) {
    this.proxied = proxied;
    }

    @Override
    public void doSomething() {
    System.out.println("SimpleProxy doSomething");
    proxied.doSomething();
    }

    @Override
    public void somethingElse(String arg) {
    System.out.println("SimpleProxy somethingElse:"+arg);
    }
    }

    public class SimpleProxyDemo {

    public static void consumer(Interface iface){
    iface.doSomething();
    iface.somethingElse("hello");
    }

    public static void main(String[] args){
    consumer(new RealObject());
    consumer(new SimpleProxy(new RealObject()));
    }
    }

    运行结果如下:

    doSomething
    somethingElse:hello
    SimpleProxy doSomething
    doSomething
    SimpleProxy somethingElse:hello

    因为consumer()接受Interface,所以它无法知道真正获得的道理是RealObject还是SimpleProxy,因为这二者都实现了Interface。但是

    SimpleProxy已经被插入到客户端和RealObject之间,因此他会执行操作,然后调用RealObject上相同的方法。

    在任何时刻,只要你想要将额外的操作从“实际”对象中分离到不同的地方,特别是当你希望能够很容易的做出修改,从没有使用额外操作转为使用这些操作

    ,或者反过来,代理就显得有用了。例如,如果你希望跟踪RealObject中方法的调用,或者希望度量这些调用的开销,那么你应该怎么做呢?这些代码你肯定

    不希望将其合并到应用中的代码,因此代理可以使你很容易的添加和移除他们。

    二、Java动态代理

    java的动态代理比代理的思想更向前迈进了一步,它可以动态的创建代理并动态的处理对所代理方法的调研。在动态代理上所做的所有调用都会被重定向到

    单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。下面是用Java动态代理重写的SimpleProxy:

    public class DynamicProxyHandler implements InvocationHandler{

    private Object proxied;

    public DynamicProxyHandler(Object proxied) {
    this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("----proxy: " + proxy.getClass()+
    ".method:" + method + ".args:" + args);
    if (args != null){
    for (Object arg:args){
    System.out.println(" " + arg);
    }
    }
    return method.invoke(proxied,args);
    }
    }

    public class SimpleDynamicProxy {

    public static void consumer(Interface iface){
    iface.doSomething();
    iface.somethingElse("hello");
    }

    public static void main(String[] args){
    RealObject real = new RealObject();
    consumer(real);

    Interface proxy = (Interface) Proxy.newProxyInstance(
    Interface.class.getClassLoader(),
    new Class[]{Interface.class},
    new DynamicProxyHandler(real)
    );
    consumer(proxy);
    }
    }

    运行结果如下:

    doSomething
    somethingElse:hello
    ----proxy: class com.sun.proxy.$Proxy0.method:public abstract void com.ProxyDesign.proxy.Interface.doSomething().args:null
    doSomething
    ----proxy: class com.sun.proxy.$Proxy0.method:public abstract void com.ProxyDesign.proxy.Interface.somethingElse(java.lang.String).args:[Ljava.lang.Object;@610455d6
    hello
    somethingElse:hello

    在该示例中,通过静态方法Proxy.newProxyInstance可以创建动态代理,这个方法的三个参数分别为:

    ClassLoader loader: 类加载器,你可以听过已经被夹在的对象获取其类加载器,然后传递给它。

    Class<?>[] interfaces:该代理实现的接口列表。

    InvocationHandler h:InvocationHandler接口的一个实现。

    动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造函数传递一个“实际”对象的引用,从而使得调用处理器在执行其中介任务时,可以将请求转发。

    而上述的invoke()方法中传递进来了代理的对象,以防你需要区分请求的来源,但是在许多情况下,你并不关心这一点。

    
    
  • 相关阅读:
    SharePoint 2010学习笔记之一:创建”最新动态”WebPart
    IE6 Png 图片透明
    C# Url 过滤特殊字符
    委托的几个实例用法
    MVC中Code First编程一些小技巧
    Javascript 学习
    NET下XML的读写操作
    C#位运算讲解与示例[转]
    DB2导入导出命令(工作中使用)
    上海长期招聘c#/c++软件工程师
  • 原文地址:https://www.cnblogs.com/junjiang3/p/8228916.html
Copyright © 2020-2023  润新知