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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© masterV 中级黑马   /  2013-8-25 19:54  /  6438 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨增坤 于 2013-8-27 17:59 编辑

下面的代码是从张老师写的代码中抽取出来的,搞不清invoke方法中的第一个参数是代理类的对象还是目标类的对象,求解。
这段代码需要和附件中的两个类一起才能运行。
  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.Collection;

  6. public class ProxyTest
  7. {
  8.         public static void main(String[] args)
  9.         {
  10.                 final ArrayList target = new ArrayList();
  11.                 Collection proxy3 = (Collection) getProxy(target, new MyAdvice());
  12.                 proxy3.add("zxx");
  13.                 proxy3.add("lhm");
  14.                 proxy3.add("bxd");
  15.                 System.out.println(proxy3.size());
  16.                 System.out.println(proxy3.getClass().getName());
  17.         }

  18.         private static Object getProxy(final Object target, final Advice advice)
  19.         {
  20.                 Object proxy3 = Proxy.newProxyInstance(
  21.                         target.getClass().getClassLoader(),
  22.                         target.getClass().getInterfaces(),
  23.                         new InvocationHandler(){
  24.                             public Object invoke(Object proxy, Method method, Object[] args)
  25.                                             throws Throwable
  26.                             {
  27.                                     advice.beforeMethod(method);
  28.                                     Object retVal = method.invoke(target, args);
  29.                                     advice.afterMethod(method);
  30.                                     return retVal;
  31.                             }
  32.                         });
  33.                 return proxy3;
  34.         }
  35. }
复制代码
Advice&MyAdvice.zip (727 Bytes, 下载次数: 300)

评分

参与人数 1技术分 +1 收起 理由
黄兴旺 + 1

查看全部评分

11 个回复

倒序浏览
Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的基础方法。
参数:
obj - 从中调用基础方法的对象
args - 用于方法调用的参数

评分

参与人数 1技术分 +1 收起 理由
黄兴旺 + 1

查看全部评分

回复 使用道具 举报
sam9204 发表于 2013-8-25 20:21
Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的基础方法 ...

能详细讲一下么,API我也看的,就是不太明白。
回复 使用道具 举报
invoke方法中的第一个参数是目标类的参数,
你把method.invoke(target,args)与proxy3.add("zxx")对照一下就会发现, invoke(Object proxy, Method method, Object[] args)正好对应proxy3.add("zxx")    中的三个元素proxy3 ,add, "zxx",
    因为已经代理类已经实现了同样的Collection,所以代理也可以使用Collection中add的方法,method.invoke(target,args)会返回实际对象的调用结果,就好比:
  add.invoke(target,"zxx")一样,对象是 target ,target中有add方法,add方法添加参数"ZXX'.只不过用的是代理的表现形式,实际操作结果是一样的
回复 使用道具 举报
魏先勇 发表于 2013-8-25 21:07
能详细讲一下么,API我也看的,就是不太明白。

不好意思,我也只是看了你代码然后去查阅了一下API,具体我也不清楚,还没学到那里{:soso_e117:}
回复 使用道具 举报
sam9204 发表于 2013-8-26 10:01
不好意思,我也只是看了你代码然后去查阅了一下API,具体我也不清楚,还没学到那里
...

哈哈,继续努力呀,,
回复 使用道具 举报
  1. Object proxy3 = Proxy.newProxyInstance(
  2.                         target.getClass().getClassLoader(),
  3.                         target.getClass().getInterfaces(),
  4.                         new InvocationHandler(){
  5.                             public Object invoke(Object proxy, Method method, Object[] args)
  6.                                             throws Throwable
  7.                             {
  8.                                     advice.beforeMethod(method);
  9.                                     Object retVal = method.invoke(target, args);
  10.                                     advice.afterMethod(method);
  11.                                     return retVal;
  12.                             }
  13.                         });
复制代码
上述是从你代码抽出部分,主要其实就是一个产生代理类实例对象的过程,这个invoke方法中传入的参数是代理类的实例对象,简单理解就是这个new InvocationHandler(),就是将目标类中需要执行的代码部分内省给了代理类,使代理类具有与目标类同样的方法,别且为其可以添加一些系统功能。
回复 使用道具 举报
是代理类的对象。谁调用了目标类的方法。就表示是谁
回复 使用道具 举报
invoke(Object proxy, Method method,Object[] args) ,Object proxy指的是代理对象,就是程序中的ArraylList。如果是代理类的话就会造成死循环,代理方法和代理的Handler的invoke不断循环调用
回复 使用道具 举报
清心玉质 发表于 2013-8-27 16:39
invoke(Object proxy, Method method,Object[] args) ,Object proxy指的是代理对象,就是程序中的ArraylLis ...

你说是目标类对象 ??如果是目标类对象 ,为什么不直接用getProxy方法中的Object target参数?
回复 使用道具 举报
魏先勇 发表于 2013-8-27 18:20
你说是目标类对象 ??如果是目标类对象 ,为什么不直接用getProxy方法中的Object target参数? ...

不是说目标类对象,是代理实例,类型是$Proxy1。
我理解的是这样:
代理对象是用来接收要实现的目标类实例,其实就是反射的意思吧,就像method是Method的实例一样,具体用哪个method不是还需要传入具体的方法名称。同理,代理对象也是需要传入具体的目标类名称,至于target参数为什么不行,你看看target的类型,它不是代理类型的,就像method不是Method类型,不能作为Method实例的吧。


回复 使用道具 举报
清心玉质 发表于 2013-8-29 15:39
不是说目标类对象,是代理实例,类型是$Proxy1。
我理解的是这样:
代理对象是用来接收要实现的目标类实 ...

嗯,我好像也有点明白了,应该是代理类实例,谢谢了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马