A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陆旭东 中级黑马   /  2013-4-4 22:15  /  1342 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

写一个ArrayList类的代理,实现和ArrayList中完全相同的功能,并可以计算每个方法运行的时间

6 个回复

倒序浏览

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ListProxy {
        public static void main(String[] args) throws Exception {
                List<String> list = newList(String.class);
                list.add("abc");
                System.out.println(list);
        }
       
       
        @SuppressWarnings("unchecked")
        public static <T> List<T> newList(Class<T> elementType) {
                return (List<T>)Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler() {
                        private List<T> realList = new ArrayList<T>();
                        public Object invoke(Object proxy, Method method, Object[] args)
                                        throws Throwable {
                                long start = System.nanoTime();
                                Object ret = method.invoke(realList, args);
                                long end = System.nanoTime();
                                System.out.println("调用" + method.getName() + "耗时:" + (end - start) + "纳秒");
                                return ret;
                        }
                });
        }
}

点评

养成加注释的习惯  发表于 2013-4-5 08:19
回复 使用道具 举报
能帮我解释下下面这段代码的意思吗?谢谢
回复 使用道具 举报
  1. public class ProxyTest{
  2.         public static void main(String[] args) {
  3.                 List myProxy3 = (List) Proxy.newProxyInstance(
  4.                                 ArrayList.class.getClassLoader(), //第一个参数(类加载器)
  5.                                 new Class[]{List.class}, //第二个参数(实现的多个接口组成的数组)
  6.                                 new InvocationHandler(){
  7.                                         ArrayList target = new ArrayList();//为动态类指定一个目标
  8.                                         @Override
  9.                                         /*调用的代理对象 proxy, 对象的方法method, 方法的参数args*/
  10.                                         public Object invoke(Object proxy, Method method, Object[] args)
  11.                                                         throws Throwable {
  12.                                                 long startTime = System.currentTimeMillis();
  13.                                                 //用传递进来的方法和参数在target对象上执行
  14.                                                 Object retVal = method.invoke(target, args);
  15.                                                 long endTime = System.currentTimeMillis();
  16.                                                
  17.                                                 long invokeTime = endTime - startTime;
  18.                                                 System.out.println(invokeTime);
  19.                                                 return retVal;
  20.                                         }
  21.                                 }//第三个参数(匿名的内部类,实现了接口InvocationHandler)
  22.                 );
  23.                
  24.                 /*每调用一次myProxy3的方法,都要去找InvocationHandler对象的invoke方法*/
  25.                 myProxy3.add("zhangsan");
  26.                 myProxy3.add("lisi");
  27.                 myProxy3.add("wangwu");
  28.         }
  29. }
复制代码
注释差不多说清楚了,这里是试验的add方法的执行时间,其他方法类似

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
我也写了一个,和楼上的差不多,就是注释多写了些,希望能帮到你。
  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. import java.util.ArrayList;
  5. import java.util.List;

  6. public class ProxyTest {
  7.         public static void main(String[] args) {
  8.                 //定义一个List对象,我称它为原始对象,即:将被代理的实例对象
  9.                 List object = new ArrayList();
  10.                
  11.                 //获取动态代理对象
  12.                 List proxyObject = (List)getProxyObject(object);
  13.                
  14.                 //以代理对象来执行原始对象的方法:
  15.                 proxyObject.add("hello");
  16.                 int size = proxyObject.size();
  17.                 System.out.println(size);
  18.         }
  19.        
  20.         //通过动态代理的方式获取一个代理对象,此代理对象在保留了原对象要执行的方法的基础上,还会执行计时操作:
  21.         public static Object getProxyObject(final Object object) {
  22.                
  23.                 Object proxyObject = (Object)Proxy.newProxyInstance
  24.                 (
  25.                         object.getClass().getClassLoader(), //原始对象的类加载器 
  26.                         object.getClass().getInterfaces(),  //原始对象的接口们
  27.                        
  28.                         //创建了一个实现InvocationHandler接口的匿名类的实例:
  29.                         new InvocationHandler() 
  30.                         {
  31.                                
  32.                                 //实现InvocationHandler接口的invoke方法:
  33.                                 @Override 
  34.                                 public Object invoke(Object o, Method m, Object[] args) throws Exception 
  35.                                 {
  36.                                         //目标方法执行前的时间记录
  37.                                         long start = System.nanoTime();
  38.                                        
  39.                                         //执行原始对象的目标方法:(此处传入的是原始对象,以及目标方法所需的参数)
  40.                                         Object retVal = m.invoke(object, args);
  41.                                        
  42.                                         //目标方法执行后的时间记录:
  43.                                         long end = System.nanoTime();
  44.                                        
  45.                                         System.out.println("原始对象的目标方法名为:" + m.getName() + ",执行耗时"+(end-start)+"纳秒!");
  46.                                        
  47.                                         //返回目标方法的返回值:
  48.                                         return retVal;
  49.                                 }
  50.                         }
  51.                 );
  52.                 return proxyObject;
  53.         }
  54. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 刘印12 于 2013-4-5 01:47 编辑

看我这个解释 你最好复制到写java代码的应用软件上,能解释的我都在上面标示了

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ListProxy {
        public static void main(String[] args) throws Exception {//相信主函数里面的东西你是能看的懂的
                List<String> list = newList(String.class);
                list.add("abc");
                System.out.println(list);
        }
        
        
        @SuppressWarnings("unchecked")//这句话是处理安全问题的你不用管
        public static <T> List<T> newList(Class<T> elementType) {//创建ArrayList的代理对象newList。。。。。
                return (List<T>)Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler() {
/*
这个地方用到了Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)的这个方法
     返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
参数:  loader - 定义代理类的类加载器 =======
  List.class.getClassLoader() 返回该类的类加载器。
        interfaces - 代理类要实现的接口列表===== new Class[]{List.class},
              指派方法调用的调用处理程序//它是一个接口要定义一个方法覆盖它的invoke()方法
*/
                        private List<T> realList = new ArrayList<T>();//创建ArrayList的对象
                        public Object invoke(Object proxy, Method method, Object[] args)
                                        throws Throwable {
                                long start = System.nanoTime();//System.nanoTime()返回最准确的可用系统计时器的当前值(Long类型的),
                                                               //以毫微秒为单位。。。。。这句就是返回代理对象开始调用方法时所用的时间
                                Object ret = method.invoke(realList, args);
/*
method.invoke(Object obj, Object... args)
          对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
参数: obj - 从中调用底层方法的对象
args - 用于方法调用的参数
返回: 使用参数 args 在 obj 上指派该对象所表示方法的结果
*/
                                long end = System.nanoTime();//这句返回的是代理对象结束运行时总共的用时
                                System.out.println("调用" + method.getName() + "耗时:" + (end - start) + "纳秒");
                                return ret;
                        }
                });
        }
}




评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1 最好用&lt;&gt;这个工具贴代码

查看全部评分

回复 使用道具 举报
追问或结贴~  记得及时处理自己的帖子~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马