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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. package proxy;

  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.InvocationHandler;
  4. import java.lang.reflect.Method;
  5. import java.lang.reflect.Proxy;
  6. import java.util.Collection;

  7. public class ProxyTest {

  8.         /**
  9.          * @param args
  10.          * ★要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,
  11.          * 全部采用静态代理方式,将是一件非常麻烦的事情!写成百上千个代理
  12.          * 类会很累
  13.          * ★JVM可以在巡行期动态生成出类的字节码,这种动态生成的类往往被
  14.          * 用作代理类,即动态代理类,
  15.          * ★JVM身材的动态类必须实现一个或多个接口,所以,JVM生成的动态类
  16.          * 只能用作具有相同接口的目标类的代理
  17.          * ★CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的
  18.          * 代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以
  19.          * 使用CGLIB库
  20.          * ★代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回
  21.          * 的结果外,还可以在代理方法中的如下四个位置加上系统功能代码
  22.          * 》1、在调用目标方法之前
  23.          * 》2、在调用目标方法之后
  24.          * 》3、在调用目标方法前后
  25.          * 》5、在处理目标方法异常的catch中
  26.          */
  27.         public static void main(String[] args)throws Exception {
  28.                 // TODO Auto-generated method stub
  29.                
  30.                 Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class.getInterfaces());
  31.                 System.out.println(clazzProxy1.getName());
  32.                
  33.                 System.out.println("-----------begin constructor list---------------");
  34. /*                $Proxy0[]
  35.                 $Proxy0[](InvocationHandler,int)*/
  36.                 Constructor[] constructors=clazzProxy1.getConstructors();
  37.                 for(Constructor constructor :constructors){
  38.                         String name=constructor.getName();
  39.                         StringBuilder sBuilder=new StringBuilder(name);
  40.                         sBuilder.append('(');
  41.                         Class[] clazzParams=constructor.getParameterTypes();
  42.                         for(Class clazzParam:clazzParams)
  43.                                 sBuilder.append(clazzParam.getName()).append(',');
  44.                         if(clazzParams.length!=0&&clazzParams!=null)
  45.                                 sBuilder.deleteCharAt(sBuilder.length()-1);
  46.                         sBuilder.append(')');
  47.                         System.out.println(sBuilder);
  48.                 }
  49.                

  50.                 System.out.println("-----------begin method list---------------");
  51.                 /*                $Proxy0[]
  52.                                 $Proxy0[](InvocationHandler,int)*/
  53.                 Method[] methods=clazzProxy1.getMethods();
  54.                 for(Method method :methods){
  55.                         String name=method.getName();
  56.                         StringBuilder sBuilder=new StringBuilder(name);
  57.                         sBuilder.append('(');
  58.                         Class[] clazzParams=method.getParameterTypes();
  59.                         for(Class clazzParam:clazzParams)
  60.                                 sBuilder.append(clazzParam.getName()).append(',');
  61.                         if(clazzParams.length!=0&&clazzParams!=null)
  62.                                 sBuilder.deleteCharAt(sBuilder.length()-1);
  63.                         sBuilder.append(')');
  64.                         System.out.println(sBuilder);
  65.                 }
  66.                
  67.                 System.out.println("-----------begin create instance list---------------");
  68.                 Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
  69.                 class MyInvocationHandler1 implements InvocationHandler{

  70.                         @Override
  71.                         public Object invoke(Object proxy, Method method, Object[] args)
  72.                                         throws Throwable {
  73.                                 // TODO Auto-generated method stub
  74.                                 return null;
  75.                         }
  76.                        
  77.                 }
  78.                 Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler1());
  79.                 System.out.println(proxy1.toString());

  80.         }

  81. }
复制代码
代码如上:
运行结果如下:
$Proxy0
-----------begin constructor list---------------
$Proxy0(java.lang.reflect.InvocationHandler)
-----------begin method list---------------
hashCode()
equals(java.lang.Object)
toString()
iterator()
isProxyClass(java.lang.Class)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
getInvocationHandler(java.lang.Object)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
wait()
wait(long,int)
wait(long)
getClass()
notify()
notifyAll()
-----------begin create instance list---------------
Exception in thread "main" java.lang.ClassCastException: $Proxy0 cannot be cast to java.util.Collection
        at proxy.ProxyTest.main(ProxyTest.java:83)

代理可以实现强转啊,代码和老师写的差不多,为什么会无法实现强转呢?求解!
还有 哪位大神 给我讲讲动态代理类,和InvocationHandler这个接口,听得有点晕!

评分

参与人数 1技术分 +1 收起 理由
SyouRai_Tsk + 1

查看全部评分

4 个回复

倒序浏览
  1. Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class.getInterfaces());
复制代码

应该是这句错了
代理类是和目标类实现相同接口的,你的程序中那个借口是Cellection,但是你在获得代理类字节码的时候,从你传的参数来看接口变成了Collection实现的接口,而不是Collection它本身
因此把Collection.class.getInterfaces()改成Collection.class

评分

参与人数 1技术分 +1 收起 理由
SyouRai_Tsk + 1

查看全部评分

回复 使用道具 举报
焚雨成灰 发表于 2014-5-3 13:28
应该是这句错了
代理类是和目标类实现相同接口的,你的程序中那个借口是Cellection,但是你在获得代理类字 ...

传入的第二个参数不是目标类实现的接口吗?Collection.class不是 自己的字节码吗?
回复 使用道具 举报
ò壞尛孩 发表于 2014-5-3 15:06
传入的第二个参数不是目标类实现的接口吗?Collection.class不是 自己的字节码吗? ...

视频中的目标类是ArrayList,不是Collection
回复 使用道具 举报
焚雨成灰 发表于 2014-5-3 16:58
视频中的目标类是ArrayList,不是Collection

还是不太懂!  newProxyInstance()传入的三个参数分别是 目标类,目标类实现的接口,和一个handler
也就是说加入 实现Collection的代理,第一个参数就是Collection.class 第二个是Class[]{Collection.class}
视频中的是ArrayList target,  所以接口就是target.getClass().getInterfaces(), ?我说的对吗?但是如果传入的
Class[]{Collection.class}  也就表示只 实现了目标类 实现Collection接口的功能的代理!?麻烦 大神再说详细点!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马