黑马程序员_基础加强之代理

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
  程序中的代理

  要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理、日志、计算方法运行时间、事务管理、等等

  编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能代码。(参看下面的原理图)

  如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后想去掉系统功能也很容易

  

package cn.itcast.day3;

import java.lang.reflect.Method;
/*
 * 定义一个忠告,实现系统功能,也叫建议,是插入进来或切入进来的建议
 */
public interface Advice {
	void beforeMethod(Method method);//定义一个在方法执行之前的抽象方法
	void afterMethod(Method method);//定义一个在方法执行之后的抽象方法
}
package cn.itcast.day3;

import java.lang.reflect.Method;

/*
 * 实现Advice
 */
public class MyAdvice implements Advice {
	long beginTime = 0;
	public void afterMethod(Method method) {
		// TODO Auto-generated method stub
		System.out.println("从传智播客毕业上班啦!");		
		long endTime = System.currentTimeMillis();
		System.out.println(method.getName() + " running time of " + (endTime - beginTime));

	}

	public void beforeMethod(Method method) {
		// TODO Auto-generated method stub
		System.out.println("到传智播客来学习啦!");
		beginTime = System.currentTimeMillis();
	}

}

package cn.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 {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		/*
		 * 调用proxy这个类,有一个静态方法getProxyClass,
		 * 为它指定一个类加载器,Collection接口
		 */
		/*
		 * JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
		 * 创建出了这样一个动态代理类
		 */
		Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		//获得这个动态代理类的名称:$Proxy0
		System.out.println(clazzProxy1.getName());
		
		System.out.println("----------begin constructors list----------");
		/*$Proxy0()
		$Proxy0(InvocationHandler,int)*/
		//取这个动态代理类下的所有构造函数
		Constructor[] constructors = clazzProxy1.getConstructors();
		for(Constructor constructor : constructors){
			//获得构造函数名
			String name = constructor.getName();
			//加入sBuilder中
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append('(');
			//获得构造函数的参数列表
			Class[] clazzParams = constructor.getParameterTypes();
			for(Class clazzParam : clazzParams){
				//将参数完整的类名加入sBuilder中
				sBuilder.append(clazzParam.getName()).append(',');
			}
			//这个参数列表不为空,且参数数组的长度不为0
			if(clazzParams!=null && clazzParams.length != 0)
				//删除逗号
				sBuilder.deleteCharAt(sBuilder.length()-1);
			sBuilder.append(')');
			//生成的动态代理类有构造方法 $Proxy0(java.lang.reflect.InvocationHandler)
			System.out.println(sBuilder.toString());			
		}

		System.out.println("----------begin methods list----------");
		/*$Proxy0()
		$Proxy0(InvocationHandler,int)*/
		//获取这个动态代理类的所有方法
		Method[] methods = clazzProxy1.getMethods();
		for(Method method : methods){
			String name = method.getName();//方法名
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append('(');
			Class[] clazzParams = method.getParameterTypes();//方法参数列表
			for(Class clazzParam : clazzParams){
				sBuilder.append(clazzParam.getName()).append(',');
			}
			if(clazzParams!=null && clazzParams.length != 0)
				sBuilder.deleteCharAt(sBuilder.length()-1);
			sBuilder.append(')');
			/*
			 * add(java.lang.Object)
			   equals(java.lang.Object)
    		   toString()
    		   ...
			 */
			System.out.println(sBuilder.toString());			
		}
		
		System.out.println("----------begin create instance object----------");
		//Object obj = clazzProxy1.newInstance();
		/*
		 * 构造一个有参的构造方法
		 */
		Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
		class MyInvocationHander1 implements InvocationHandler{

			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
		
		}
		//用这个构造方法去new一个instance,传入一个具体的参数:new MyInvocationHander1()
		//有了Collection这个对象
		Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
		
		System.out.println(proxy1);//结果为null
		proxy1.clear();//调用无返回值的方法,成功
		//proxy1.size();//调用有返回值的方法,失败,报空指针异常
		//System.out.println("111111111111111");
		
		//new一个动态类的实例对象
		Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){

			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				return null;
			}
			
		});
		
		final ArrayList target = new ArrayList();			
		Collection proxy3 = (Collection)getProxy(target,new MyAdvice());//指定一个目标ArrayList对象
		proxy3.add("zxx");
		proxy3.add("lhm");
		proxy3.add("bxd");
		System.out.println(proxy3.size());
		System.out.println(proxy3.getClass().getName());
	}

	private static Object getProxy(final Object target,final Advice advice) {
		Object proxy3 = Proxy.newProxyInstance(
				target.getClass().getClassLoader(),//获得这个目标ArrayList对象的类加载器
				/*new Class[]{Collection.class},//多个接口*/
				target.getClass().getInterfaces(),//获得这个目标ArrayList对象的所有接口
				new InvocationHandler(){
				
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {

						/*long beginTime = System.currentTimeMillis();
						Object retVal = method.invoke(target, args);
						long endTime = System.currentTimeMillis();
						System.out.println(method.getName() + " running time of " + (endTime - beginTime));
						return retVal;*/
						
						/*
						 * 为目标类的方法增加一个系统功能,即计算方法的运行时间
						 */
						//在方法执行之前执行这个方法,实现系统功能
						advice.beforeMethod(method);	
						Object retVal = method.invoke(target, args);
						//在方法执行之后执行这个方法,实现系统功能
						advice.afterMethod(method);
						return retVal;						
						
					}
				}
				);
		return proxy3;
	}

}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值