1. 程式人生 > >設計模式學習之動態代理模式

設計模式學習之動態代理模式

import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

class InvocationHandlerImpl implements InvocationHandler {

	public Object object;

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		Object result = method.invoke(object, args);// 注意如果方法是void,返回的是null
		return result;
	}

}
interface Handler{
	void execute();
}
class HandlerImpl1 implements Handler{

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		System.err.println("1執行");
		
	}
	
}
class HandlerImpl2 implements Handler{

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		System.err.println("2執行");
	}
	
}


public class Test {
	public static void main(String[] args) {
		Handler h = new HandlerImpl1();
		InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl();
		invocationHandlerImpl.object = h;
		Handler hh =  (Handler) Proxy.newProxyInstance(Test.class.getClassLoader(), h.getClass().getInterfaces(), invocationHandlerImpl);
		hh.execute();

	}
}

以下測試更為全面:

		Handler h = new HandlerImpl1();
		InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl();
		invocationHandlerImpl.object = h;
		Class<?>[] cs= h.getClass().getInterfaces();//獲取介面集合
		System.err.println(cs[0]);
		Handler hh =  (Handler) Proxy.newProxyInstance(Test.class.getClassLoader(),cs, invocationHandlerImpl);	//invocationHandlerImpl要代理的物件
		
		hh.execute();	
		
		InvocationHandler i = Proxy.getInvocationHandler(hh);//獲取實際型別
		Class<?> c =Proxy.getProxyClass(Test.class.getClassLoader(), h.getClass().getInterfaces());//被代理的動態物件的class物件
		//以下程式碼分析這個動態代理class的資訊
		Method[] ms = c.getMethods();
		for(Method m:ms){
			System.err.println(m.getName());
			Class<?>[] cms = m.getParameterTypes();
			System.err.print("引數為:");
			for(Class<?> cm : cms){
				System.err.print(cm.getSimpleName()+"--");
			}
			
			if(cms.length==0){
				System.err.print("無參函式");
			}
			System.err.println("");
		}
		boolean b1 = Proxy.isProxyClass(h.getClass());
		boolean b2 = Proxy.isProxyClass(c);
		System.err.println(i.toString());
		System.err.println(c.toString());
		System.err.println(b1);
		System.err.println(b2);
		

	}
}

列印資訊為:

interface wwx.test.Handler
前置處理
1執行
equals
引數為:Object--
toString
引數為:無參函式
hashCode
引數為:無參函式
execute
引數為:無參函式
isProxyClass
引數為:Class--
newProxyInstance
引數為:ClassLoader--Class[]--InvocationHandler--
getInvocationHandler
引數為:Object--
getProxyClass
引數為:ClassLoader--Class[]--
wait
引數為:無參函式
wait
引數為:long--int--
wait
引數為:long--
getClass
引數為:無參函式
notify
引數為:無參函式
notifyAll
引數為:無參函式

[email protected]
class wwx.test.$Proxy0
false

true


解釋:

以下都是動態代理類的,代理方法

equals
引數為:Object--
toString
引數為:無參函式
hashCode
引數為:無參函式
execute
引數為:無參函式
isProxyClass
引數為:Class--
newProxyInstance
引數為:ClassLoader--Class[]--InvocationHandler--
getInvocationHandler
引數為:Object--
getProxyClass
引數為:ClassLoader--Class[]--
wait
引數為:無參函式
wait
引數為:long--int--
wait
引數為:long--
getClass
引數為:無參函式
notify
引數為:無參函式
notifyAll

引數為:無參函式

和ide給出一樣:



總結:

java的動態代理僅僅支援interface的代理,這裡必須注意,不能對class進行動態代理,根本原因就是Java在

本質上多繼承就是行不通的。javaScript可以動態代理,而且很容易實現,因為它是指令碼語言,指令碼語言可以

在程式碼中執行程式碼,那就很easy了啊。