51_52创建动态类的实例对象及调用其方法

package com.itcast.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
/*
 * 三种得到代理类对象的方式
 * 一、直观型
 * 二、匿名内部类型
 * 三、从字节码一步到位型(推荐使用)
 */
public class ProxyTest {
    public static void main(String[] args)throws Exception {
        //得到代理类的字节码
        Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
        //clazzProxy1.newInstance();//不能这么干,因为该newInstance调用的是那个不带参数的构造方法
        
        /**一、最直观的方式创建代理类对象***/
        //01.得到有参数的构造方法
        System.out.println("begin create instance");
        Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
        //newInstance时要有InvocationHandler实例,但是InvocationHandler是一个接口,所以定义了这个类
        class InvocationHandlerImpl_1 implements InvocationHandler{

            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                // TODO Auto-generated method stub
                return null;
            }
            
        }
        //02.得到实例对象
        Collection proxy1=(Collection) constructor.newInstance(new InvocationHandlerImpl_1());
        System.out.println(proxy1.toString());//
        proxy1.clear();//无返回值函数
        //proxy1.size();//有返回值函数--报空指针--没有目标类
        
        
        /**二、使用匿名内部类得到代理类对象****/
        Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                
                return null;
            }
        });
        
        
        /**三、一步到位得到代理类对象****/
        Collection proxy3 =  (Collection)Proxy.newProxyInstance(
                Collection.class.getClassLoader(), 
                new Class[]{Collection.class}, 
                new InvocationHandler(){
                    ArrayList target=new ArrayList();
                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        
                        long beginTime=System.currentTimeMillis();
                        Object reVal=method.invoke(target, args);
                        long endTime=System.currentTimeMillis();
                        System.out.println(method.getName()+" running "+(endTime-beginTime));
                        return reVal;
                    }
                }
            );
        
        proxy3.add("123");
        proxy3.add("456");
        System.out.println(proxy3.size());
        
        System.out.println(proxy3.getClass().getName());//com.sun.proxy.$Proxy0,为什么不是ArrayList?
        //原因 Object没有把所有的方法都派发给 代理类构造方法的参数---InvocationHandler来处理
        
        /* java.lang.reflect.Proxy API
        在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法的调用将按照与编码
        和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的 invoke 方法,如上所述。
        传递到 invoke 的 Method 对象的声明类是 java.lang.Object。
        代理类不重写从 java.lang.Object 继承的代理实例的其他公共方法,
        所以这些方法的调用行为与其对 java.lang.Object 实例的操作一样。 */

    }
}
posted @ 2015-02-05 16:16  刘江龙  阅读(334)  评论(0编辑  收藏  举报