java_高新代理(黑马程序员)


------- android培训、java培训、期待与您交流! ----------

我们为什么用到代理?

我们想一下在生活中会有这么一些事:你有一些东西要买,但你有病了下不了床,你必须让别人代替你买回来,这就是代理!

在java中的Proxy可以帮我们实现代理,也就是说可以动态的创建代理类!依靠的是Proxy

所以我们要首先动态生成Proxy代理的类:

getProxyClass(ClassLoader loader, Class... interface)

返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。该代理类将由指定的类加载器定义,并将实现提供的所有接口。如果类加载器已经定义了具有相同排列接

口的代理类,那么现有的代理类将被返回;否则,类加载器将动态生成并定义这些接口的代理类.

Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

这也就是说要生成一个你需要的东西的Class。也就是动态加载过程!但是始终用的是Proxy!接下来就是需要构造方法了!

Proxy.getClass().getConstructor(InvocationHandler.class);

需要注意的是在这个获取构造方法的过程中,Proxy没有无参数构造方法。只有一个传递InvocationHandler.class参数的构造函数方法!

所以你这样Constructor constructor = clazz.getConstructor(InvocationHandler.class);

当你获得了构造函数的时候也就是意味着你可以生成一个你所需的类了!

接下来就可以生成了调用newInstance方法!

Collection c = (Collection) constructor.newInstance(new InvocationHandler(){});这样就生成了!你需要覆盖的方法是InvcoationHandler的invoke的方法

就是public Object invoke(Object Proxy, Method method, Object[] args)!里面要增加Object ret = method.invoke(a, args);return ret;

那么到处你就可以使用你的动态代理类的对象c了!c调用方法会调用代理的增加的方法!

	public static void method_1() throws Exception
	{
		Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		Constructor constructor = clazz.getConstructor(InvocationHandler.class);
		Collection c = (Collection) constructor.newInstance(new InvocationHandler(){
			ArrayList a = new ArrayList();
			@Override
			public Object invoke(Object Proxy, Method method, Object[] args)
					throws Throwable {
				System.out.println("runing");
				Object ret = method.invoke(a, args);
				return ret;
			}});
		System.out.println(c.add("xxx"));;
	}

以上就是代理的代码,可以说是有一定的费解!那么我们就来分析一下原理!

1.我们调用动态代理为的是,代理调用一个类a的方法,使得调用前后添加想增加的函数!

2.我们要用到Proxy,用这个类来动态的加载我们的类a,并且获得的就是a的Class文件,接着获得a的构造方法,要注意的是我们获得a的构造方法其实是Proxy的带有Invcationhandler的方法,也就是说要获得的a的构造函数是带InvcationHandler.Class的方法.再获得a的对象的实例,我们会在获得的过程中调用够着函数!也就是说此时还要传入Invcationhandler的子类,我们用匿名内部类!

3.其实原理和反射差不多。但是InvcationHandler的原理是什么?这是重点

在InvcationHandler中有一个invoke方法。传入的参数为Object Proxy, Method method, Object[] args这三个参数的意义是Proxy是代理,method就是你以后要调用a方法的反射!args就是method'的参数。那么你以后要调用a的方法,也就是这里代理的方法了!这样在这个invoke调用前加上beforemethod或者是aftermethod就可以加载到以后的调用前后了!

那么还有一种简写方法:

public static void method_2()
	{
		final ArrayList a =new ArrayList();//含有一点要注意的就是调用的类是final的这样才可以传入 匿名内部类
		Collection c = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[] {Collection.class}, 
				new InvocationHandler()
		{
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				System.out.println("runing");
				Object ret = method.invoke(a, args);
				return ret;
			}	
		});
		System.out.println(c.add("xxx"));
	}

这种方法中只要一个方法就可以返回我们一个需要的类a对象了!

我们可以抽象出来,形成一个动态代理类:

	public static void method_3()
	{
		ArrayList a =new ArrayList();
		MyAdvice myadvice = new MyAdvice();
		Collection o =  (Collection) getProxy(a,myadvice);
		o.add("xxx");
		o.add("sas");
		System.out.println(o);
		
	}
	public static Object getProxy(final Object target,final advice Myadvice)
	{
		Object o = Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), 
				new InvocationHandler(){
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						Myadvice.beforeMthod();
						Object ret = method.invoke(target, args);
						Myadvice.afterMethod();
						return ret;
					}
		});
		return o;
	}
}
class MyAdvice implements advice
{
	@Override
	public void afterMethod()
	{
		System.out.println("this is before method ");
	}
	@Override
	public void beforeMthod() {
		System.out.println("this is after method ");
	}
}
 interface advice
{
	void beforeMthod();
	void afterMethod();
}

其中我们只需修改MyAdvice的方法就可以了!加载时调用getProxy。熟悉了代理机制就很好理解这个抽象出来的代理了!


------- android培训、java培训、期待与您交流! ----------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值