Java核心技术之代理

什么是代理(proxy)?使用代理服务器翻过墙的都知道那大概是怎么一回事。比如,我想访问google,结果GFW不允许。假如存在于某地的一台主机可以访问google,并且可以提供访问google的服务,这时我们向这台主机发出访问google的请求,这台主机然后将我们的请求转发给google,并且将google的响应内容返回给我们,那么这个主机就是一个代理了。

Java中的代理是这样定义的,利用代理可以在运行时创建一个实现了一组给定接口的新类。那么具体用在哪儿呢?例如:

  • Routing method calls to remote servers
  • Associating user interface events with actions in a running program
  • Tracing method calls for debugging purposes

第一种用法没接触过,不作讨论。

第二种用法如下,假设有一个标签为Load的按钮,它的事件处理只包含下面一个方法调用frame.loadData(),使用匿名内部类的写法如下:

loadButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent event) {
        frame.loadData();
    }
});

使用EventHandler类可以自动地创建这样一个监听器:

EventHandler.create(ActionListener.class, frame, "loadData");

第三种用法,用于调试时跟踪方法调用。示例代码及代码解释如下:

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;

public class ProxyTest 
{
    public static void main(String[] args)
    {
        Object[] elements = new Object[1000];

        for (int i = 0; i < elements.length; i++)
        {
            Integer value = i + 1;
            InvocationHandler handler = new TraceHandler(value);
            Object proxy = Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler);
            elements[i] = proxy;
        }

        Integer key = new Random().nextInt(elements.length) + 1;
        int result = Arrays.binarySearch(elements, key);
        if (result >= 0) System.out.println(elements[result]);
    }
}

class TraceHandler implements InvocationHandler
{
    private Object target;

    public TraceHandler(Object c)
    {
        target = c;
    }
    @Override
    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
    {
        System.out.print(target);
        System.out.print("."+m.getName()+"(");

        if (args != null)
        {
            for (int i = 0; i < args.length; i++)
            {
                System.out.print(args[i]);
                if (i < args.length - 1)System.out.print(", ");

            }
        }
        System.out.println(")");
        return m.invoke(target, args);
    }
}

以上代码跟踪了Arrays.binarySearch方法的调用过程,由于这个方法不是我们编写的,无法在该方法中添加打印语句之类的实现跟踪。那么该如何做呢?由于binarySearch方法能够排序任何实现了Comparable接口的对象数组。于是我们可以创建一个对象数组,里面的每个元素都是一个代理对象(由Proxy.newProxyInstance方法创建),该对象实现了Comparable接口并且代理了一个Integer原对象,每个原对象被一个InvocationHandler对象持有,每当在代理对象上调用了一个方法m,InvocationHandler对象的invoke方法就被回调,在此处就可以添加一些打印语句等,最后再将方法m施加在原对象上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值