- 為其他對象提供一種代理,以控制對這個對象的訪問。
一、代理模式分類
- 1、遠程代理:為不同地理的對象,提供局域網(wǎng)代表對象(類似于客戶端和服務(wù)器端)
- 2、虛擬代理:根據(jù)需要將消耗資源很大的對象進行延遲,真正需要的時候進行創(chuàng)建。(網(wǎng)頁中 圖片的加載,先用一張?zhí)摂M的圖片進行顯示,等圖片加載完成后再進行顯示)
- 3、保護代理:控制用戶的訪問權(quán)限。(注冊成功后才能發(fā)帖)
- 4、智能應用代理:提供對目標對象一些額外的服務(wù)。(火車站)
二、靜態(tài)代理
- 代理和被代理對象在代理之前是確定的,實現(xiàn)了相同的接口或抽象類
- 靜態(tài)代理實現(xiàn)方式:繼承和聚合
繼承:創(chuàng)建一個類(代理類)繼承被代理類(實現(xiàn)相同的接口),在代理類中調(diào)用父類的被代理方法,在方法的前后增加代理的業(yè)務(wù)邏輯
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("汽車結(jié)束行駛。。。"+"用時:"+
(endtime-starttime)+"毫秒");
}
}
聚合:一個類中調(diào)用另一個類的對象(兩者實現(xiàn)相同接口)。在代理類中聲明被代理類的對象,并通過構(gòu)造方法將對象傳進來(初始化)。在代理類的接口方法中調(diào)用被代理類對象的方法,并在方法前后增加相應代理業(yè)務(wù)邏輯。
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("汽車結(jié)束行駛。。。"+"用時:"+
(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("日志結(jié)束");
}
}
Car car=new Car();
CarTimeProxy ctp=new CarTimeProxy(car);
CarLogProxy clp=new CarLogProxy(ctp);
clp.move();
/*
*日志開始
*汽車開始行駛。。。
*汽車行駛中。。。
*汽車結(jié)束行駛。。。用時:137毫秒
*日志結(jié)束
*/
當想要先輸出汽車行駛代理,在輸出日志代理,只需要更改main方法中代理的順序即可。
三、動態(tài)代理

Paste_Image.png

Paste_Image.png
- 動態(tài)代理步驟
1、創(chuàng)建一個類,實現(xiàn)InvocationHandler接口,并實現(xiàn)invoke方法,添加業(yè)務(wù)邏輯(實現(xiàn)原有功能并添加額外功能)
2、創(chuàng)建被代理的類以及接口
3、調(diào)用Proxy的靜態(tài)方法newProxyInstance(loader, interfaces, h)
4、通過代理調(diào)用方法
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
/*
* proxy:被代理的對象
* method:被代理對象的方法
* args:方法的參數(shù)
* 返回值:調(diào)用方法的返回值
*/
@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("汽車結(jié)束行駛。。。"+"用時:"+
(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();
}
}
}
調(diào)用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)生一個子類,通過方法攔截技術(shù)攔截所有父類方法的調(diào)用
public class CglibProxy implements MethodInterceptor {
//創(chuàng)建代理類屬性
private Enhancer enhance=new Enhancer();
//傳遞需要代理的類
public Object getProxy(Class clazz){
//設(shè)置創(chuàng)建子類的類
enhance.setSuperclass(clazz);
enhance.setCallback(this);
return enhance.create();
}
/*
* 攔截所有目標類方法的調(diào)用
* obj:目標類的實例
* m:目標方法的返回對象
* args:方法的參數(shù)
* proxy:代理類實例
*/
@Override
public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("日志開始。。。");
//代理類調(diào)用父類方法
proxy.invokeSuper(obj, args);
System.out.println("日直結(jié)束。。。");
return null;
}
}
CglibProxy proxy=new CglibProxy();
Train t=(Train) proxy.getProxy(Train.class);
t.move();