設計模式學習之動態代理模式
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
引數為:無參函式
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了啊。