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 [] ages)
    {
     Object[] elements = new Object[1000];
     for(int i=0;i<elements.length;i++)
     {
     Integer value = i+1;
     Class[] interfaces = value.getClass().getInterfaces();
     InvocationHandler handler = new TraceHandler(value);
     Object proxy = Proxy.newProxyInstance(null, interfaces, 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 t)
    {
     target = t;
    }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.print(target);
System.out.print("."+ method.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 method.invoke(target, args);
}

}
帮我吧这个程序写下注释,并解释下功能。
还有就是java中的 proxy 是什么概念?用途..最好举个例子 
谢谢各位大侠了

解决方案 »

  1.   


    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[] ages) {
    //创建了可以装1000个Object对象的数组
    Object[] elements = new Object[1000];
    //把产生1000个代理对象
    Class[] interfaces = Integer.class.getInterfaces();
    for (int i=0;i<interfaces.length;i++){
    System.out.println(interfaces);
    }
    for (int i = 0; i < elements.length; i++) {
    //代理对象的原型是Integer对象,值是从1-1000
    Integer value = i + 1;
    //取出Integer类实现的所有接口(其实这可以改成Class[] interfaces = Integer.class.getInterfaces();放到循环外)
    //Class[] interfaces = value.getClass().getInterfaces();
    //为原型对象设置方法调用处理器(InvocationHandler)
    InvocationHandler handler = new TraceHandler(value);
    //产生代理对象
    Object proxy = Proxy.newProxyInstance(null, interfaces, handler);
    //把代理对象装入数组
    elements[i] = proxy;
    }
    //随机产生一个1-1000的整数
    Integer key = new Random().nextInt(elements.length) + 1;
    //在代理对象数组中二分查找是否存在跟key值相同的对象
    int result = Arrays.binarySearch(elements, key);
    //如果找到了就调用这个代理对象的toString()方法
    if (result > 0)
    System.out.println(elements[result]);
    }
    }class TraceHandler implements InvocationHandler {
    private Object target; public TraceHandler(Object t) {
    target = t;
    }
    //方法调用处理器的核心内容:当调用代理对象的任何方法时,都要先调用本方法
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    //调用原型对象的toString()方法并输出到屏幕
    System.out.print(target);
    //接着打印 .被调用的方法名字(
    System.out.print("." + method.getName() + "(");
    //如果方法调用带参数,则打印出参数
    if (args != null) {
    for (int i = 0; i < args.length; i++) {
    //打印参数对象的toSting()
    System.out.print(args[i]);
    //如果不是最后一个参数,还要打个,号
    if (i < args.length - 1)
    System.out.print(", ");
    }
    }
    //最后打印一个回)号
    System.out.println(")");
    //调用原对象方法,并返回原对象方法的返回值
    return method.invoke(target, args);
    }
    }
      

  2.   

    不带反射时原来的程序:
    import java.util.Arrays;
    import java.util.Random;public class ProxyTest2 {
    public static void main(String[] ages) {
    Object[] elements = new Object[1000];
    for (int i = 0; i < elements.length; i++) {
    Integer value = i + 1;
    elements[i] = value;
    }
    Integer key = new Random().nextInt(elements.length) + 1;
    int result = Arrays.binarySearch(elements, key);
    if (result > 0)
    System.out.println(elements[result]);
    }}
      

  3.   

    大侠   //方法调用处理器的核心内容:当调用代理对象的任何方法时,都要先调用本方法
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {这里的method参数,args参数
    是不是Integer类中的 compareTo()方法?和参数
      

  4.   

    看不带反射的代码:
    其实就是产生了1-1000的整数数组
    然后随机产生一个1-1000的整数
    用二分法到数组中查找是否存在这个随机数(肯定存在嘛,呵呵)
    找到就打印那么关于Proxy对象的代码起了什么作用呢?
    其实就是让你看到了Arrays.binarySearch(elements, key);的运行过程,和System.out.print(Object)的运行过程
    以某次运行为例,打印的结果如下:
    500.compareTo(725)
    750.compareTo(725)
    625.compareTo(725)
    687.compareTo(725)
    718.compareTo(725)
    734.compareTo(725)
    726.compareTo(725)
    722.compareTo(725)
    724.compareTo(725)
    725.compareTo(725)
    725.toString()
    725可以看到二分查找是从正中间开始的--500,对比调用的是对象的compareTo方法,
    而且可以看到Arrays.binarySearch对比的实现代码是用数组对象的compareTo方法,而不是查找对象的compareTo方法
    最后2行是System.out.println(elements[result]);产生的,
    可以看到System.out.print时,是调用对象的toString()方法
      

  5.   

    还有就是  return method.invoke(target, args);这句 的target 指的是那个方法?
      

  6.   

    给过连接给你看看,以前也有人提问过有关代理的东西,你看看先http://topic.csdn.net/u/20081207/17/98d8de2c-f5c4-424d-90eb-c50eb3ea8f22.html
      

  7.   

    这个程序就是Proxy的例子我们通常会用Proxy在不破坏原来代码的前提下给原来的类赋予新的功能
    比如我们要测试某方法的运行时间,通常的办法都得改代码(加上时间测试代码)
    有了Proxy就不用了!
    我们可以做一个Proxy,在它里面加测试代码,这样即使我们拿到的是jar,也可以测了,而且不担心测完了要删测试的代码的问题。Proxy在我们日常的工作中经常被用于--拦截器、统一事务处理、日志等
      

  8.   


    任何方法的调用都要走这关!
    上面看到的725.toString() 就是调用toString()方法产生的
      

  9.   


    private Object target;
    target就是被代理的对象(原对象),不是方法!
      

  10.   


    大侠 我的理解是这样的
    1.遇到指定接口需要的全部方法
    2.Object类中的 全部方法
    才会走  处理器的方法  对吗?
    所以   int result = Arrays.binarySearch(elements, key);
            //如果找到了就调用这个代理对象的toString()方法
            if (result > 0)
                System.out.println(elements[result]);
    Arrays.binarySeacrch()方法的时候 会用到 代理时放入的compareable接口
    这样处理器就会跟踪compareTo()方法toString()方法为什么会跟踪到那
      

  11.   

    呵呵 这个看糊涂了  
    我想问的是 method 这里指的是那个方法?
      

  12.   

    public Object invoke(Object proxy, Method method, Object[] args)这个方法 我也没有看见任何调用或 给它传参的地方
    难道是运行时?调用你能给我说下 这个程序的大体流程吗?
      

  13.   

    method 是指被代理对象的所调用的方法。
      

  14.   

    这个理论上是怎样的我还不清楚
    不过从运行的结果看对象自己的或者从祖先继承的方法肯定是被拦截了。接口的方法可能跟创建代理对象时
    Proxy.newProxyInstance(null, interfaces, handler);
    interfaces参数有关。
      

  15.   

    java有时让我很头疼啊!头疼!
      

  16.   


    你把它看成拦截器是对的!
    当我们需要调用代理对象的方法时,被拦住了(呵呵,怎么象税务局盯咱们的工资?)
    然后交给invoke(Object proxy, Method method, Object[] args)处理
    第二个参数就是我们需要调用的方法,第三个参数就是我们调方法的参数
      

  17.   

    这个程序就是Proxy的例子 
      

  18.   

    其实二楼已经讲的很清晰了我再补充下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[] ages) {        Object[] elements = new Object[1000];
            //把产生1000个Integer类型的class类的接口
            Class[] interfaces = Integer.class.getInterfaces();
            for (int i=0;i<interfaces.length;i++){
                System.out.println(interfaces);
            }
            for (int i = 0; i < elements.length; i++) {
                Integer value = i + 1;
              
              )
                //因为handler继承了InvocationHandler所以本身有个Invoke()方法;
                 InvocationHandler handler = new TraceHandler(value);
                //产生代理对象并当需要调用taget类的目标方法的时候就有代理类来调用~
                 //你看出来没有?Integer本身和InvocationHandler组成了一个代理类
               //所以只要Integer想调用什么方法就得先调用invoke()方法来实现调用而不是直接调用
                Object proxy = Proxy.newProxyInstance(null, interfaces, handler);
                //把代理对象装入数组
                elements[i] = proxy;
            }
            //随机产生1-1000的整数
            Integer key = new Random().nextInt(elements.length) + 1;
            //在代理对象数组中二分查找是否存在跟key值相同的对象
             //因为二分查找的时候Integer要调用Compare to()方法所以他要先调用Invoke()方法
            int result = Arrays.binarySearch(elements, key);
            //同样他也要想调用代理类的Invoke()方法通过代理类来实现本身方法的调用
           //其实代理类本身也有Integer类的接口所以有具有所有他的方法
            if (result > 0)
                System.out.println(elements[result]);
        }
    }class TraceHandler implements InvocationHandler {
        private Object target;    public TraceHandler(Object t) {
            target = t;
        }
        //方法调用处理器的核心内容:当调用代理对象的任何方法时,都要先调用本方法
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
               //当代理类调用Integer的方法的时候就会来到这个方法体里。method也就是要调用的方法
               //而Object数组是用来装method的参数的 。他也就是相当于 invoke (Object proxy, Method compareTo(), 302)         
                    System.out.print(target);
            //接着打印 .被调用的方法名字(
            System.out.print("." + method.getName() + "(");
            //如果方法调用带参数,则打印出参数
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    //打印参数对象的toSting()
                    System.out.print(args[i]);
                    //如果不是最后一个参数,还要打个,号
                    if (i < args.length - 1)
                        System.out.print(", ");
                }
            }
            //最后打印一个回)号
            System.out.println(")");
            //调用原对象方法,并返回原对象方法的返回值
            return method.invoke(target, args);
        }
    }