首先分析動態代理模式中的3個角色:
1.抽象角色:static proxy中它可以是抽象類,但是dynamic proxy中它只能是介面
2.真實角色:就是實現了抽象角色中的方法罷了
3.代理角色:最噁心的就是動態代理裡面的這個代理角色了。它要持有真實角色的引用。
它涉及到一個介面和一個類,InvocationHandler介面和Proxy類。根據JDK文檔說,InvocationHandler介面是要被一個類別實現的,這個類別的實例是一個代理物件對應的handler物件。當代理物件的一個方法被調用,則會把該方法編碼並分配給它對應的handler物件的invoke方法中去調用!
複製代碼代碼如下:
//抽象角色:
public interface AbstractRole
{
public void show();
}
//真實角色:
public class RealRole implements AbstractRole
{
@Override
public void show(){ System.out.println("show me your house"); }
}
//代理角色:
//我覺得這只是一個偽代理罷了,偽代理是我自己想出來的= =! ,因為它實際上是代理對應的handler
public class Handler implements InvocationHandler
{
private Object realRole; // 代理角色中需要有真實角色的引用,定義為Object類型則通用
public Handler(Object realRole)
{ this.realRole = realRole; }
@Override
public Object invoke(Object proxy, Method method, Object[] args)
{
System.out.println("Give me your money"); // 這是代理角色自己增加的額外功能罷了
method.invoke(this.realRole, args); //透過反射呼叫真實角色的方法
System.out.println("Ok...house is yours");//這是代理角色自己增加的額外功能罷了
}
public Object factory()//透過工廠方法產生真正的代理角色
{
return Proxy.newProxyInstance(this.getClass().getClassLoader(), this.realObject.getClass().getInterfaces(), this); //Proxy中的newProxyInstance方法有兩個很重要的特點!第一個是動態建立一個代理類,若輸出好像是名叫$Proxy0的類別;第二是透過動態建立的這個類別產生一個實例。
}
}
//客戶端:
public class Test
{
public static void main(String[] args)
{
RealRole realRole = new RealRole();//想要代理哪一個真實角色就new出這個真實角色
Handler handler = new Handler(realRole);//這裡產生了代理類別對應的handler了,我也想叫他偽代理對象
AbstractRole proxy = (AbstractRole)handler.factory();//透過工廠方法產生代理對象
}
}
以上或許會想這裡代理角色怎麼能強轉為抽象角色呢?原因在於newProxyInstance方法,這個方法太interesting了~就如上面說的,它會自動產生一個類,然後透過類別產生代理物件。其實這個類別就實現了抽象角色類別了,為什麼?因為第二個參數已經指明了它實現哪些介面了。所以可以強轉了,強轉之後就可以呼叫抽象角色中的方法了
proxy.show();//好!注意這句了,我在最開始有紅體字標出來,“會把該方法編碼並分配給它對應的handler對象的invoke方法中去調用!” 就因為這句話,所以proxy.show()就是把show方法傳到了handler物件中的invoke方法中去了,當然也跟著show方法的參數了,不過這裡show方法沒有參數。所以proxy.show()這句話實際上就是呼叫了handler物件中的invoke方法。