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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© gzbbxu 中级黑马   /  2013-6-25 09:57  /  1543 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 孙百鑫 于 2013-6-30 08:17 编辑

动态代理的Proxy.newProxyInstance到底返回的是什么东西啊?还有InvocationHandler的子类,到底是干啥的?表示不理解。。还有,就是重写的方法invoke方法中,Object proxy这个参数到底该怎么理解?好像没有用到吧?有什么作用呢?

评分

参与人数 1技术分 +1 收起 理由
刘凯 + 1 赞一个!

查看全部评分

6 个回复

倒序浏览
首先是什么时候用到代理?
就是在已有一个类的情况下,你需要在这个类的方法上,添加其他的功能,那么你就可以用到代理。
你可以用另外一个方法(其实就是InvocationHandler的invoke方法)把目标类的方法封装起来,然后再这个方法的前后,添加上代码实现你想实现的功能,其实这就是InvocationHandler要实现的功能。
Proxy.newProxyInstance方法返回的就是一个指定接口的代理类实例。
举个例子应该更清楚一些:

  1. <P> </P>
复制代码
proxy3.add("zxx");//这行代码有三个元素,proxy3、add、"zxx"。
执行这句代码的时候,proxy3传给InvocationHandler的invoke方法的第一个参数Object proxy,
add传给第二个参数Method method,"zxx"传给第三个参数Object[] args。这样InvocationHandler才会知道,是哪个代理调用的哪个方法,使用的是什么参数。
整段代码就相当于在ArrayList的add方法的前后加了①②③这三行代码,InvocationHandler的invoke方法返回的还是method.invoke(target, args);的返回值。
至于你说invoke的Object proxy参数没用到,因为这个invoke方法不是显示的去调用,我想应该是里面封装了吧。
回复 使用道具 举报
代码没上去,不好意思。
首先是什么时候用到代理?
就是在已有一个类的情况下,你需要在这个类的方法上,添加其他的功能,那么你就可以用到代理。
你可以用另外一个方法(其实就是InvocationHandler的invoke方法)把目标类的方法封装起来,然后再这个方法的前后,添加上代码实现你想实现的功能,其实这就是InvocationHandler要实现的功能。
Proxy.newProxyInstance方法返回的就是一个指定接口的代理类实例。
举个例子应该更清楚一些:

  1. <P>Collection proxy3 =(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),
  2. new Class[]{Collection.class},
  3. new InvocationHandler(){
  4. ArrayList target = new ArrayList();
  5. public Object invoke(Object proxy, Method method,
  6. Object[] args) throws Throwable {
  7. long beginTime = System.currentTimeMillis();//①</P>
  8. <P>Object retVal = method.invoke(target, args);
  9. long endTime = System.currentTimeMillis();//②
  10. System.out.println(method.getName()+" running time is "+(endTime-beginTime));//③
  11. return retVal;
  12. }

  13. });
  14. //执行一次proxy3的方法,就会执行一次InvocationHandler的invoke方法
  15. proxy3.add("zxx");//返回值就是invoke方法的返回值</P>
复制代码
proxy3.add("zxx");//这行代码有三个元素,proxy3、add、"zxx"。
执行这句代码的时候,proxy3传给InvocationHandler的invoke方法的第一个参数Object proxy,
add传给第二个参数Method method,"zxx"传给第三个参数Object[] args。这样InvocationHandler才会知道,是哪个代理调用的哪个方法,使用的是什么参数。
整段代码就相当于在ArrayList的add方法的前后加了①②③这三行代码,InvocationHandler的invoke方法返回的还是method.invoke(target, args);的返回值。
至于你说invoke的Object proxy参数没用到,因为这个invoke方法不是显示的去调用,我想应该是里面封装了吧。

评分

参与人数 1技术分 +1 收起 理由
刘凯 + 1 赞一个!

查看全部评分

回复 使用道具 举报
我的愚见:

代理这种设计模式我感觉有点类似于装饰设计模式,只不过没有接收一个对象罢了。
它的存在是为了解决AOP的问题,AOP是啥呢?AOP就是将各种交叉业务模块化的一个过程。那么问题又来了,你每个类都去写代理岂不是累死人,假设有1000个类你岂不是要写1000个代理?   
动态代理说:“不要怕,还有我”。那么啥是动态代理呢?动态代理就是为了完善代理的一种手段,它可以生成一个类,这个类是作为一个目标类的代理类的。这就是动态类。
我们通常所说的动态代理实际上都是在构建一个动态类实例。ok,那么怎么构建?那么invocationhandler这玩意就用上了,这玩意名字挺长,你也不用去查字典它叫啥意思,你就记住invocationhandler它是一个接口,就是在构建一个动态类实例时需要接受的一个参数罢了(它的实现类)。然而这个invocationhandler参数自身又有3个参数,这3个参数分别是方法,目标类,参数。方法和参数是系统自己传递的,而目标类是我们传递的。
我们在构建一个动态类实例的时候有三种方式。一种是老老实实的获取构造器,然后newInstance,然后newinstance的时候传入一个事先构建好的invocationhandler实现类。第二种方法就是第一种方法的匿名内部类形式,第三种方法就是我楼上那种方法。

评分

参与人数 1技术分 +1 收起 理由
刘凯 + 1 赞一个!

查看全部评分

回复 使用道具 举报
同上                              
回复 使用道具 举报
wangpan 发表于 2013-6-25 11:55
代码没上去,不好意思。
首先是什么时候用到代理?
就是在已有一个类的情况下,你需要在这个类的方法上,添 ...

很明了,谢谢
回复 使用道具 举报
楼主您好,帖子长时间没有动态我已经将您的帖子改成已解决。如有问题请私密我哦~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马