以反射的方式实现的定向代理

package question3;

import java.lang.reflect.Method;
import java.util.ArrayList;

/*
 * 	写一个ArrayList类的代理,其内部实现和ArrayList中完全相同的功能,
 * 	并可以计算每个方法运行的时间。
 * 
 *  解题方式二
 *  1.反射机制实现代理调用
 *  2.实现统一的代理工厂方法来实现代理的创建
 *  3.为该方法的耗时计算实现线程安全,以精度为纳秒计算
 *  4.为目标ArrayList实现线程安全
 *  
 *  优点:摒弃了第一种方式的大量代码创建量
 *  	  相对于第一种方式,可以调用ArrayList的上层
 *  	  方法和本地方法,而不仅是上层方法
 *  缺点:反射方式总归还是会导致目标方法调用耗时多一些
 *  	  而invoke方法的隐式类型方式,不熟悉Arraylist
 *  	  的话很容易出错,同时这样的代理局限性很明显,
 *  	  仅仅只支持ArrayList
 *  
 *  注:1秒=1 000 000 000纳秒 jdk api中以毫微秒表示纳秒
 */
public class ArrayListProxy_2<E>
{
	@SuppressWarnings("unchecked")
    public static void main(String[] args)
	{
		ArrayListProxy_2<String> proxy = ArrayListProxy_2.factory();
		proxy.invoke("add", new Class[]{Object.class}, new Object[]{"zhangsan"});
		proxy.invoke("size", null, null);
		
		//本行如果不注释,会抛异常,因为没有这个方法
		//不过并不会导致程序终止
		//proxy.invoke("lalalala", null, null);
		
		proxy.invoke("get", new Class[]{int.class}, new Object[]{0});
	}
	
	/**
	 * 此代理的目标ArrayList,该成员只有代理类
	 * 可以持有,所以不应该暴露给用户,而是私有
	 */
	private ArrayList<E> target = new ArrayList<E>();
	
	/*
	 * 为该代理实现工厂方法,并私有化构造方法
	 * 实现统一的代理创建方式
	 */
	private ArrayListProxy_2(){}
	public static final <E> ArrayListProxy_2<E> factory()
	{
		return new ArrayListProxy_2<E>();
	}
	
	/**
	 * 本类的代理方法,用以实现ArrayList的所有方法的
	 * 代理调用,并统计耗时,本方法是线程安全的
	 * 
	 * <p><font color=red>代理方法并不应该因为异常而导致程序终止(退出),
	 * 而是应该以日志方式记录该异常信息,以表明该代理
	 * 的使用者存在显式的错误</font>
	 * 
	 * @param methodName 需要调用的方法名称
	 * @param parameterTypes 该方法的参数类型列表
	 * @param parameters 该方法的参数列表
	 * @return 该方法的返回值;如果出现异常,并不会被抛出
	 * 		       控制台仅以错误方式显示该异常的信息,但不会
	 * 	                包括异常堆栈信息,而同时返回null
	 */
	public Object invoke(String methodName, Class<? extends Object>[] parameterTypes, Object[] parameters)
	{
		try
        {
			Object returnValue = null;
			Method method = target.getClass().getMethod(methodName, parameterTypes);
			long taken = 0;
			/*
			 * 同步实现的目标方法调用以及耗时统计
			 */
			synchronized (target)
            {
				if(null != methodName)
				{
					taken = System.nanoTime();
					returnValue = method.invoke(target, parameters);
			        taken = System.nanoTime() - taken;
				}
            }
			/*
			 * 控制台输出目标方法调用的详细信息,包括报名,类名,方法名
			 * 以及实参的参数列表(传入的实际参数列表),数组不在此列。。。
			 * 并输出返回值和耗时
			 */
	        System.out.print(target.getClass().getName()+"."+method.getName()+"(");
	        if(null != parameters)
		        for (int i = 0; i < parameters.length; i++)
	            {
		        	System.out.print(parameters[i]);
		            if(i != parameters.length - 1)
		            	System.out.print(", ");
		        }
	        System.out.println(") return "+returnValue+"      times taken by "+taken+" ns");
	        /*
	         * 将返回值返回给使用者
	         */
	        return returnValue;
        }
        catch (Exception e)
        {
        	/*
        	 * 木有用e.printStackTrace(),运行时异常会导致程序挂掉
        	 * 所以仅以错误方式输出,这里应该是需要写进log里面,log4j
        	 * 找不到了。。。(┬_┬)
        	 */
        	System.out.flush();
        	System.err.println(e.getClass().getName()+":"+e.getMessage());
        	System.err.flush();
        	return null;
	    }
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值