在java的動態代理機制中,有兩個重要的類或接口,一個是 InvocationHandler(Interface)、另外一個則是 Proxy(Class),這一個類和接口是實現咱們動態代理所必須用到的。java
示例:數組
public class DynamicProxyTest { interface UserService { public abstract void add(); } interface UserService2 { public abstract void add2(); } static class UserServiceImpl implements UserService, UserService2 { public void add() { System.out.println("----- add -----"); } public void add2() { System.out.println("----- add 2-----"); } } static class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { super(); this.target = target; } public Object getProxy() { /** * Thread.currentThread().getContextClassLoader(: 一個ClassLoader對象,定義了由哪一個ClassLoader對象來對生成的代理對象進行加載 * arget.getClass().getInterfaces(): 一個Interface對象的數組,表示的是我將要給我須要代理的對象提供一組什麼接口,若是我提供了一組接口給它,那麼這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了 * this: 一個InvocationHandler對象,表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪個InvocationHandler對象上 */ return Proxy.newProxyInstance(Thread.currentThread() .getContextClassLoader(), target.getClass().getInterfaces(), this); } /** * proxy: 咱們所代理的那個真實對象 * method: 咱們所要調用真實對象的某個方法的Method對象 * args: 調用真實對象某個方法時接受的參數 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("----- before -----"); Object result = method.invoke(target, args); System.out.println("----- after -----"); return result; } } /** * @param args */ public static void main(String[] args) { UserService userService = new UserServiceImpl(); MyInvocationHandler invocationHandler = new MyInvocationHandler( userService); UserService proxy = (UserService) invocationHandler.getProxy(); proxy.add(); ((UserService2)proxy).add2(); } }
執行結果:markdown
----- before ----- ----- add ----- ----- after ----- ----- before ----- ----- add 2----- ----- after -----
代理實現過程當中的問題說明:
1. 這個代理對象是由誰且怎麼生成的?函數
Proxy.newProxyInstance方法的實現裏會經過建立一個代理類,並返代理實例供咱們使用
咱們拿的的代理類是在編譯過程當中有jdk自動生成的. 類裏會實現各個接口的方法,實現的方法裏會調用invoke,例如:this
public final void add() throws { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
實現InvocationHandler 這個接口的實例會有invoke方法,而且會執行spa
Object result = method.invoke(target, args);
經過獲得執行後的返回值,add方法就在此時被真正的實例調用add方法代理
編譯成功後能夠去$Proxy0.class文件查看內容code
總結:
一個典型的動態代理建立對象過程可分爲如下四個步驟:
一、經過實現InvocationHandler接口建立本身的調用處理器 IvocationHandler handler = new InvocationHandlerImpl(…);
二、經過爲Proxy類指定ClassLoader對象和一組interface建立動態代理類
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
三、經過反射機制獲取動態代理類的構造函數,其參數類型是調用處理器接口類型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
四、經過構造函數建立代理類實例,此時需將調用處理器對象做爲參數被傳入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
爲了簡化對象建立過程,Proxy類中的newInstance方法封裝了2~4,只需兩步便可完成代理對象的建立。
生成的ProxySubject繼承Proxy類實現Subject接口,實現的Subject的方法實際調用處理器的invoke方法,而invoke方法利用反射調用的是被代理對象的的方法(Object result=method.invoke(proxied,args))對象
動態代理與混型的應用繼承
示例代碼:
public class DynamicProxyMixin { class TwoTuple<A, B> { public A first; public B second; public TwoTuple(A a, B b) { this.first = a; this.second = b; } } interface TimeStamped { long getStamped(); } static class TimeStampedImpl implements TimeStamped { private final long date; public TimeStampedImpl() { date = new Date().getTime(); } public long getStamped() { return date; } } interface SerialNumbered { long getSerialNumbered(); } static class SerialNumberedImpl implements SerialNumbered { private static long counter = 1; private final long serialNumber = counter++; public long getSerialNumbered() { return serialNumber; } } interface Basic { void set(String val); String get(); } static class BasicImpl implements Basic { private String value; public void set(String val) { value = val; } public String get() { // TODO Auto-generated method stub return value; } } static class MixinProxy implements InvocationHandler { Map<String, Object> delegateByMethodMap; private MixinProxy(TwoTuple<Object, Class<?>> ...pairs) { delegateByMethodMap = new HashMap<String, Object>(); for (TwoTuple<Object, Class<?>> pair : pairs) { for (Method method : pair.second.getMethods()) { String methodName = method.getName(); if (!delegateByMethodMap.containsKey(methodName)) { delegateByMethodMap.put(methodName, pair.first); } } } } public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable { String methodName = method.getName(); return method.invoke(delegateByMethodMap.get(methodName), arg2); } public static Object newInstance(TwoTuple<Object, Class<?>> ...pairs){ Class[] interfaces = new Class[pairs.length]; for (int i = 0, count = interfaces.length; i < count; i++) { interfaces[i] = (Class) pairs[i].second; } ClassLoader loader = pairs[0].first.getClass().getClassLoader(); return Proxy.newProxyInstance(loader, interfaces, new MixinProxy(pairs)); } } /** * @param args */ public static void main(String[] args) { Object proxyObject = MixinProxy.newInstance(new TwoTuple(new BasicImpl(), Basic.class), new TwoTuple(new TimeStampedImpl(), TimeStamped.class), new TwoTuple(new SerialNumberedImpl(), SerialNumbered.class)); Basic b = (Basic) proxyObject; SerialNumbered serialNumbered = (SerialNumbered) proxyObject; TimeStamped timeStamped = (TimeStamped) proxyObject; b.set("hello"); System.out.println(b.get()); System.out.println(serialNumbered.getSerialNumbered()); System.out.println(timeStamped.getStamped()); } }
執行結果:
hello 1 1494841280897
經過動態代理獲得的proxyObject實例就是一個混型類型,擁有多個接口功能.