代理是基本的設計模式之一,它是爲了提供額外的或不同的操作,而插入的用來代替“實際”對象的對象。這些操作通常涉及與“實際”對象的通信,因此代理通常充當着中間人的角色。
而Java的動態代理比代理的思想更向前邁進了一步,它可以動態地創建代理並動態地處理對所代理方法的調用。在動態代理上所做的所有調用都會被重定向到單一的調用處理器上,它的工作是揭示調用的類型並確定相應的對策。下面是用來展示動態代理的一個簡單示例:
public interface Interface {
void doSomething();
void somethingElse(String arg);
}
public class RealObject implements Interface {
@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething");
}
@Override
public void somethingElse(String arg) {
// TODO Auto-generated method stub
System.out.println("somethingElse " + arg);
}
}
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
// TODO Auto-generated constructor stub
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("proxy: " + proxy.getClass() + ", method: " + method + ", args: " + args);
if(args != null){
for(Object arg : args){
System.out.println(arg);
}
}
return method.invoke(proxied, args);
}
}
public class DynamicProxyTest {
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("bonobo");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("*******************未使用代理前*******************");
RealObject real = new RealObject();
consumer(real);
System.out.println("*******************使用代理後*******************");
InvocationHandler handler = new DynamicProxyHandler(real);
Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, handler);
consumer(proxy);
}
}
通過調用靜態方法Proxy.newProxyInstance()可以創建動態代理,該方法有三個參數:
1、一個類加載器(classloader)。作爲Java安全模型的一部分,對於系統類和從因特網上下載下來的類,可以使用不同的類加載器。
2、一個Class對象數組,每個元素都是需要實現的接口。
3、一個調用處理器,即InvocationHandler接口的一個實現。
動態代理可以將所有調用重定向到調用處理器,因此通常會向調用處理器的構造器傳遞給一個“實際”對象的引用,從而使得調用處理器在執行其中介任務時,可以將請求轉發。