- 為其他對象提供一種代理绍赛,以控制對這個對象的訪問。
一辑畦、代理模式分類
- 1吗蚌、遠程代理:為不同地理的對象,提供局域網(wǎng)代表對象(類似于客戶端和服務器端)
- 2航闺、虛擬代理:根據(jù)需要將消耗資源很大的對象進行延遲褪测,真正需要的時候進行創(chuàng)建猴誊。(網(wǎng)頁中 圖片的加載潦刃,先用一張?zhí)摂M的圖片進行顯示,等圖片加載完成后再進行顯示)
- 3懈叹、保護代理:控制用戶的訪問權限乖杠。(注冊成功后才能發(fā)帖)
- 4、智能應用代理:提供對目標對象一些額外的服務澄成。(火車站)
二胧洒、靜態(tài)代理
- 代理和被代理對象在代理之前是確定的,實現(xiàn)了相同的接口或抽象類
- 靜態(tài)代理實現(xiàn)方式:繼承和聚合
繼承:創(chuàng)建一個類(代理類)繼承被代理類(實現(xiàn)相同的接口)墨状,在代理類中調用父類的被代理方法卫漫,在方法的前后增加代理的業(yè)務邏輯
public class Car implements Moveable {
@Override
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽車行駛中。肾砂。列赎。");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class Car2 extends Car {
@Override
public void move() {
long starttime=System.currentTimeMillis();
System.out.println("汽車開始行駛。镐确。包吝。");
super.move();
long endtime=System.currentTimeMillis();
System.out.println("汽車結束行駛。源葫。诗越。"+"用時:"+
(endtime-starttime)+"毫秒");
}
}
聚合:一個類中調用另一個類的對象(兩者實現(xiàn)相同接口)。在代理類中聲明被代理類的對象息堂,并通過構造方法將對象傳進來(初始化)嚷狞。在代理類的接口方法中調用被代理類對象的方法,并在方法前后增加相應代理業(yè)務邏輯。
public class Car3 implements Moveable {
private Car car;
public Car3(Car car) {
super();
this.car = car;
}
@Override
public void move() {
long starttime=System.currentTimeMillis();
System.out.println("汽車開始行駛床未。褂乍。。");
car.move();
long endtime=System.currentTimeMillis();
System.out.println("汽車結束行駛即硼。逃片。。"+"用時:"+
(endtime-starttime)+"毫秒");
}
}
在創(chuàng)建一個日志代理只酥,
public class CarLogProxy implements Moveable {
private Moveable m;
public CarLogProxy(Moveable m) {
super();
this.m = m;
}
@Override
public void move() {
System.out.println("日志開始");
m.move();
System.out.println("日志結束");
}
}
Car car=new Car();
CarTimeProxy ctp=new CarTimeProxy(car);
CarLogProxy clp=new CarLogProxy(ctp);
clp.move();
/*
*日志開始
*汽車開始行駛褥实。。裂允。
*汽車行駛中损离。。绝编。
*汽車結束行駛僻澎。。十饥。用時:137毫秒
*日志結束
*/
當想要先輸出汽車行駛代理窟勃,在輸出日志代理,只需要更改main方法中代理的順序即可逗堵。
三秉氧、動態(tài)代理
Paste_Image.png
Paste_Image.png
- 動態(tài)代理步驟
1、創(chuàng)建一個類蜒秤,實現(xiàn)InvocationHandler接口汁咏,并實現(xiàn)invoke方法,添加業(yè)務邏輯(實現(xiàn)原有功能并添加額外功能)
2作媚、創(chuàng)建被代理的類以及接口
3攘滩、調用Proxy的靜態(tài)方法newProxyInstance(loader, interfaces, h)
4、通過代理調用方法
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
/*
* proxy:被代理的對象
* method:被代理對象的方法
* args:方法的參數(shù)
* 返回值:調用方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long starttime=System.currentTimeMillis();
System.out.println("汽車開始行駛纸泡。漂问。。");
method.invoke(target);
long endtime=System.currentTimeMillis();
System.out.println("汽車結束行駛弟灼。级解。。"+"用時:"+
(endtime-starttime)+"毫秒");
return null;
}
}
創(chuàng)建接口
public interface Moveable {
public void move();
}
實現(xiàn)接口類
public class Car implements Moveable {
@Override
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽車行駛中田绑。勤哗。。");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
調用Proxy的靜態(tài)方法
public class Test {
/*
* 動態(tài)代理測試類
*/
public static void main(String[] args) {
Car car=new Car();
InvocationHandler h=new TimeHandler(car);
ClassLoader loader=car.getClass().getClassLoader();
Class[] interfaces=car.getClass().getInterfaces();
/*
* loader:被代理類的類加載器
* interfaces:實現(xiàn)的接口
* h:InvocationHandler實現(xiàn)
*/
Moveable m=(Moveable) Proxy.newProxyInstance(loader, interfaces, h);
m.move();
}
}
四掩驱、CGLIB代理
- 針對類來實現(xiàn)的代理
- 對指定目標類產(chǎn)生一個子類芒划,通過方法攔截技術攔截所有父類方法的調用
public class CglibProxy implements MethodInterceptor {
//創(chuàng)建代理類屬性
private Enhancer enhance=new Enhancer();
//傳遞需要代理的類
public Object getProxy(Class clazz){
//設置創(chuàng)建子類的類
enhance.setSuperclass(clazz);
enhance.setCallback(this);
return enhance.create();
}
/*
* 攔截所有目標類方法的調用
* obj:目標類的實例
* m:目標方法的返回對象
* args:方法的參數(shù)
* proxy:代理類實例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("日志開始冬竟。。民逼。");
//代理類調用父類方法
proxy.invokeSuper(obj, args);
System.out.println("日直結束泵殴。。拼苍。");
return null;
}
}
CglibProxy proxy=new CglibProxy();
Train t=(Train) proxy.getProxy(Train.class);
t.move();