一,什么是代理
利用代理可以在運行時創(chuàng)建一個實現(xiàn)了一組給定接口的新類,這種只有編譯時無法確定需要實現(xiàn)那個接口時才有必要使用
二,何時使用代理
有一個表示接口Class對象,它的準確類型編譯時候無法知道,想要構造一個實現(xiàn)這些接口的類,想要構建一個實現(xiàn)這些接口的類,需要使用NewInstance或反射出這個類的構造器,但是,不能實例化一個接口,需要在程序處于運行時定義一個新類
代理類可以解決這個問題:運行的時候創(chuàng)建全新的類,能實現(xiàn)指定的接口,具有下列的方法
①指定接口鎖需要的全部方法
②Object類中的全部方法
注:不能在運行的時候定義這些方法的代碼,需要提供一個調(diào)用處理器,調(diào)用處理器實現(xiàn)了IncocationHandler接口的類對象,這個接口只有一個方法
Object Invoke(objetct proxy,Method method,Object[] args),無論何時調(diào)用代理器對象的方法,都會調(diào)用invoke方法,并向其傳遞method對象和原始的調(diào)用參數(shù)
三,創(chuàng)建代理對象和運用場景
創(chuàng)建一個代理對象,需要使用proxy類的newProxyInstance方法
①ClassLoader loader:指定當前目標對象使用類加載器,獲取加載器的方法是固定的
②Class<?>[] interfaces:目標對象實現(xiàn)的接口類型,使用泛型方式確認類型,獲取接口類型的方法是固定的
③InvocationHandler h;事件處理,執(zhí)行目標對象的方法時,會觸發(fā)事件處理器的方法,會把當前執(zhí)行目標對象的方法作為參數(shù)傳入
例子
public interface Hello {
void doSomething();
}
public class HelloImpl implements Hello {
@Override
public void doSomething() {
System.out.println("HelloImpl doSomething");
}
}
/**
* 代理類
*/
public class ProxyHandler implements InvocationHandler {
private Object proxyed;
public ProxyHandler(Object proxy) {
proxyed = proxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
System.out.println("proxy working");
return method.invoke(proxyed, args);
}
}
public static void main(String[] args) {
Hello hello = new HelloImpl();
Hello proxy = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(),
new Class[]{Hello.class}, new ProxyHandler(hello));
proxy.doSomething();
}
輸出結(jié)果
proxy working
HelloImpl doSomething
運用1.
路由對遠程方法的調(diào)用
運用2.
在程序運行區(qū)間,將用戶接口事件與動作關聯(lián)起來
運用3.
為調(diào)試,跟蹤方法調(diào)用
運用4. spring aop