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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© tommy 中级黑马   /  2014-9-6 23:08  /  3933 人查看  /  15 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

5黑马币
想动态代理TreeSet集合,代理类能用的方法只能是Set集合里面的方法吗?难道不能用代理类的对象调用TreeSet集合特有的方法吗?(比如pollFirst方法)
求大神解答!!!


package com.lianxi.test02;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Test1 {

    public static void main(String[] args) {
        
        final TreeSet ts = new TreeSet();
        Set proxy = (Set)Proxy.newProxyInstance(TreeSet.class.getClassLoader(),
                TreeSet.class.getInterfaces(),
                new InvocationHandler() {
                    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        long beginTime = System.currentTimeMillis();
                        Object retVal = method.invoke(ts, args);
                        long endTime = System.currentTimeMillis();
                        System.out.println(method.getName()+" running time is "+(endTime-beginTime));
                        return retVal;
                    }
                });
        
        proxy.add("Tom");
        proxy.add("Tommy");
        proxy.add("Ben");
        
        System.out.println(proxy.toString());
    }
   
}

最佳答案

查看完整内容

你传入的那个接口就可以调用哪个接口的方法,代理其实就是把接口的方法都给封装起来,然后加点功能代码,然后再调用你已经实现的方法,以达到功能增强的功能。 对于代理类能用的方法只能是Set集合里面的方法吗?这个问题,如果你传入的是Set集合,肯定只能调用Set集合的方法不能调用TreeSet集合的特有方法,因为代理类找不到!!! ...

15 个回复

倒序浏览
你传入的那个接口就可以调用哪个接口的方法,代理其实就是把接口的方法都给封装起来,然后加点功能代码,然后再调用你已经实现的方法,以达到功能增强的功能。
对于代理类能用的方法只能是Set集合里面的方法吗?这个问题,如果你传入的是Set集合,肯定只能调用Set集合的方法不能调用TreeSet集合的特有方法,因为代理类找不到!!!
回复 使用道具 举报
目前我的想法是同上,在代理的时候你可以自己定义一个TreeSet类实例作为Advice传进去,只不过,在获得代理类之后执行每个方法都会调用Advice
回复 使用道具 举报
格子、 发表于 2014-9-7 08:38
你传入的那个接口就可以调用哪个接口的方法,代理其实就是把接口的方法都给封装起来,然后加点功能代码,然 ...

那你写个代理TreeSet集合的代理类,能调用TreeSet集合自身特有的方法而不是Set接口的方法
回复 使用道具 举报
tommy 发表于 2014-9-7 17:08
那你写个代理TreeSet集合的代理类,能调用TreeSet集合自身特有的方法而不是Set接口的方法 ...

你难道不知道 你之所以调用不了特有方法是因为你传入的不是TreeSet接口而是它实现的接口么!!!自己看看TreeSet.class.getInterfaces(),
回复 使用道具 举报
格子、 发表于 2014-9-7 19:08
你难道不知道 你之所以调用不了特有方法是因为你传入的不是TreeSet接口而是它实现的接口么!!!自己看看 ...

首先TreeSet是类不是接口,而且我传入的是TreeSet。
动态类是服务于接口的,代理类和被代理类实现同一个接口,也就是说代理类能调用的方法只有被代理类实现接口的方法,而不包括被代理类自身的方法。  我是这么理解的,不知道对不对!!     

我现在很好奇代理类能不能调用被代理类自身的方法。你写个程序我看看,学习下!!
回复 使用道具 举报
tommy 发表于 2014-9-7 19:42
首先TreeSet是类不是接口,而且我传入的是TreeSet。
动态类是服务于接口的,代理类和被代理类实现同一个 ...

貌似CGLIB库可以实现,生成目标类的子类。。。
回复 使用道具 举报
格子、 发表于 2014-9-7 19:44
貌似CGLIB库可以实现,生成目标类的子类。。。

我知道这个,没有别的方法了吗??
回复 使用道具 举报
tommy 发表于 2014-9-7 19:58
我知道这个,没有别的方法了吗??

嗯嗯,肯定是有的,但是现在我不知道。。。
回复 使用道具 举报
继续学习~
回复 使用道具 举报
本帖最后由 旭辉lin 于 2014-9-8 21:08 编辑
  1. package bao3;

  2. import java.lang.reflect.Method;
  3. import java.util.TreeSet;
  4. import net.sf.cglib.proxy.Enhancer;
  5. import net.sf.cglib.proxy.MethodInterceptor;
  6. import net.sf.cglib.proxy.MethodProxy;

  7. public class CglibDemo {
  8.         public static void main(String[] args) {
  9.                 CGlibProxyFactory factory = new CGlibProxyFactory();
  10.                 TreeSet ts = (TreeSet) factory.createProxyInstance(new TreeSet());
  11.                 System.out.println(ts.getClass().getName());
  12.         }
  13. }

  14. class CGlibProxyFactory implements MethodInterceptor {

  15.         private Object targetObject;

  16.         public Object createProxyInstance(Object targetObject) {
  17.                 this.targetObject = targetObject; // 传入用户类

  18.                 Enhancer enhancer = new Enhancer(); // Enhancer是cglib的核心类

  19.                 // 将用户类设为 Enhancer对象的superclass属性,,即设为 Enhancer对象的父类
  20.                 enhancer.setSuperclass(this.targetObject.getClass());
  21.                 // 设 Enhancer对象的Callbacks属性,要求必须是Callback接口类型
  22.                 enhancer.setCallback(this);

  23.                 return enhancer.create(); // 生成代理对象
  24.         }

  25.         @Override
  26.         public Object intercept(Object arg0, Method arg1, Object[] arg2,
  27.                         MethodProxy arg3) throws Throwable {
  28.                 return arg1.invoke(targetObject, null);
  29.                 // return null;
  30.         }

  31. }
复制代码


回复 使用道具 举报

这是用的CGLIB库直接生成的子类?没用过这个库。。。
回复 使用道具 举报
hah m我没仔细你
回复 使用道具 举报
tommy 中级黑马 2014-9-18 23:21:53
14#

什么意思??
回复 使用道具 举报
本帖最后由 郑飞 于 2014-9-25 22:24 编辑

还是有办法的啊 用自定义子类去实现TreeSet 然后这个类 实现一个自定义接口
被代理对象:TreeSet子类的实例 接口:这个自定义接口

相当于给TreeSet的子类 做动态代理 应该可以满足你的需要
回复 使用道具 举报
本帖最后由 郑飞 于 2014-9-25 22:50 编辑

平时练习改的 稍微改了下 有不好的地方请高手告知 供楼主参考吧
  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. import java.util.TreeSet;


  5. public class ProxyDemo extends TreeSet implements BeProxyAble{//自定义TreeSet子类

  6.         /**
  7.          * @param args
  8.          */
  9.        
  10.         static ProxyDemo mySet = new ProxyDemo();//传入invocation中
  11.        
  12.         public static void main(String[] args)throws Exception {
  13.                
  14.                 mySet.add("aa");
  15.                 mySet.add("bb");
  16.                 mySet.add("cc");
  17.                 System.out.println("原集合有3个元素"+mySet);//原集合有3个元素
  18.                 BeProxyAble setProxy =(BeProxyAble) Proxy.newProxyInstance(ProxyDemo.class.getClassLoader(),
  19.                                 new Class[]{BeProxyAble.class},new MyInvocationHandler());
  20.                 setProxy.myPollFirst();
  21.                 System.out.println("现集合有2个元素"+mySet);//现集合有2个元素
  22.         }
  23.         public Object myPollFirst()//用TreeSet中的pollFirst()方法来实现自定义接口中的方法;
  24.         {       
  25.                 System.out.println("pollFirst()");
  26.                 return super.pollFirst();
  27.         }
  28. }

  29. interface BeProxyAble//自定义接口
  30. {
  31.         public Object myPollFirst();//在invocation中调用此方法
  32. }

  33. class MyInvocationHandler implements InvocationHandler
  34. {

  35.         @Override
  36.         public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
  37.         {
  38.                 System.out.println("befor!..");
  39.                 method.invoke(ProxyDemo.mySet, null);
  40.                 System.out.println("after!..");
  41.                 return null;
  42.         }
  43.        
  44. }
复制代码






回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马