靜態代理
代理模式可以在不修改被代理對象的基礎上,通過擴展代理類,進行一些功能的附加與增強。值得注意的是,代理類和被代理類應該共同實現一個接口,或者是共同繼承某個類。
public interface Movie {
void play();
}
真正的實現類
public class RealMovie implements Movie {
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("您正在觀看電影 《肖申克的救贖》");
}
}
靜態代理 對movie進行代理
public class Cinema implements Movie {
RealMovie movie;
public Cinema(RealMovie movie) {
super();
this.movie = movie;
}
@Override
public void play() {
guanggao(true);
movie.play();
guanggao(false);
}
public void guanggao(boolean isStart){
if ( isStart ) {
System.out.println("電影馬上開始了,爆米花、可樂、口香糖9.8折,快來買啊!");
} else {
System.out.println("電影馬上結束了,爆米花、可樂、口香糖9.8折,買回家吃吧!");
}
}
}
public class ProxyTest {
public static void main(String[] args) {
RealMovie realmovie = new RealMovie();
Movie movie = new Cinema(realmovie);
movie.play();
}
}
動態代理
上面代碼中 Cinema 類是代理,我們需要手動編寫代碼讓 Cinema 實現 Movie 接口,而在動態代理中,我們可以讓程序在運行的時候自動在內存中創建一個實現 Movie 接口的代理,而不需要去定義 Cinema 這個類。這就是它被稱為動態的原因。
假設有一個大商場,商場有很多的柜臺,有一個柜臺賣茅臺酒
//賣酒的許可證
public interface SellWine {
void mainJiu();
}
public class MaotaiJiu implements SellWine {
@Override
public void mainJiu() {
// TODO Auto-generated method stub
System.out.println("我賣得是茅臺酒。");
}
}
public class GuitaiA implements InvocationHandler {
private Object pingpai;
public GuitaiA(Object pingpai) {
this.pingpai = pingpai;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("銷售開始 柜臺是: "+this.getClass().getSimpleName());
method.invoke(pingpai, args);
System.out.println("銷售結束");
return null;
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MaotaiJiu maotaijiu = new MaotaiJiu();
InvocationHandler jingxiao1 = new GuitaiA(maotaijiu);
SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(),
MaotaiJiu.class.getInterfaces(), jingxiao1);
dynamicProxy.mainJiu();
}
}
方法解析
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
loader 自然是類加載器,interfaces 代碼要用來代理的接口,h 一個 InvocationHandler 對象
InvocationHandler
InvocationHandler 是一個接口,官方文檔解釋說,每個代理的實例都有一個與之關聯的 InvocationHandler 實現類,如果代理的方法被調用,那么代理便會通知和轉發給內部的 InvocationHandler 實現類,由它決定處理。
因為,Proxy 動態產生的代理會調用 InvocationHandler 實現類,所以 InvocationHandler 是實際執行者。
紅框中 $Proxy0 就是通過 Proxy 動態生成的。
$Proxy0 實現了要代理的接口。
$Proxy0 通過調用 InvocationHandler 來執行任務。
上一篇代理模式回顧:
http://www.lxweimin.com/p/ed281dcf9fa7
參考文章:
https://blog.csdn.net/briblue/article/details/73928350