JDK的代理模式

jdk的代理模式

1.代理模式的定義:

爲其他對象提供一種代理一控制對這個對象的訪問,代理對對象起到中介作用,用於去掉部分功能服務或者是增加一些額外的服務

2.靜態代理:

代理和被代理之間的關係是確定的,他們都是實現相同的接口或者是繼承相同的抽象類;

 

創建接口

public interface Moveable {

void move();

}

創建車實現Moveable方法

public class Car implements Moveable {

@Override

public void move() {

//實現開車

try {

Thread.sleep(new Random().nextInt(1000));

System.out.println("汽車行駛中....");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

① 繼承的方式:

創建Car2_以繼承的方式實現靜態代理:

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) + "毫秒!");

}

}

② 聚合的方式:

創建Car3__以聚合的方式實現靜態代理:

public class Car3 implements Moveable {

public Car3(Car car) {

super();

this.car = car;

}

private Car car;

@Override

public void move() {

long starttime = System.currentTimeMillis();

System.out.println("汽車開始行駛....");

car.move();

long endtime = System.currentTimeMillis();

System.out.println("汽車結束行駛.... 汽車行駛時間:"

+ (endtime - starttime) + "毫秒!");

}

}

兩者之間都可以實現靜態代理,但是相比之下,使用聚合的方式更好:

比如: 上面的例子只是增加了時間記錄那麼需要創建一個Car2,那麼如果在增加一個記錄行駛日誌呢?那麼就要再創建一個Car4,再增加一個權限呢?那麼就需要再創建一個Car5來繼承Car4,.........這樣的話沒增加一個功能就需要創建一個實例.但是使用聚合的方式就不會這樣了

同樣創建一個move接口:

public interface Moveable {

void move();

}

再創建一個實例Car實現Moveable接口

public class Car implements Moveable {

@Override

public void move() {

//實現開車

try {

Thread.sleep(new Random().nextInt(1000));

System.out.println("汽車行駛中....");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

創建時間代理_用於記錄時間

public class CarTimeProxy implements Moveable {

public CarTimeProxy(Moveable m) {

super();

this.m = m;

}

private Moveable m;

@Override

public void move() {

long starttime = System.currentTimeMillis();

System.out.println("汽車開始行駛....");

m.move();

long endtime = System.currentTimeMillis();

System.out.println("汽車結束行駛.... 汽車行駛時間:"

+ (endtime - starttime) + "毫秒!");

}

}

創建日誌代理_用於記錄日誌

public class CarLogProxy implements Moveable {

public CarLogProxy(Moveable m) {

super();

this.m = m;

}

private Moveable m;

@Override

public void move() {

System.out.println("日誌開始....");

m.move();

System.out.println("日誌結束....");

}

}

創建測試類

public static void main(String[] args) {

Car car = new Car();

CarLogProxy clp = new CarLogProxy(car);

CarTimeProxy ctp = new CarTimeProxy(clp);

clp.move();//此時是先執行日誌,再執行記錄行駛時間

ctp.move();//此時是先執行記錄行駛時間,再執行記錄日誌

}

這樣可以看出聚合相比於繼承要靈活了很多

但是,像權限,日誌,時間這種公共的代理,後面如果再創建了一個其他對象,如飛機,火車,自行車呢?那是不是就要創建不同的實例呢?然後這種情況下就需要用到動態代理了

3.動態代理

動態代理的原理圖如下所示:

Java動態代理類位於java.lang.reflect包下,一般主要涉及到一下兩個類:

(1) Interface InvocationHandler :

該接口中僅定義了一個方法:public object invoke (Object obj,Method method, Object[] args)在實際使用的時候,第一個參數obj一般是指代理類,method是被代理的方法,args爲該方法的參數數組,這個抽象方法在代理類中被動態實現;

(2)Proxy :

該類即爲動態代理類

static Object newProxyInstance(ClassLoader loader,Class[] interf aces,

InvocationHandler h): 返回代理類的一個實例,返回後的代理類可以當作被

代理類使用(可使用被代理類的在接口中聲明過的方法)

示例:

創建時間處理的handler

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {

public TimeHandler(Object target) {

super();

this.target = target;

}

private Object target;

/*

* 參數:

* proxy 被代理對象

* method 被代理對象的方法

* args 方法的參數

* 返回值:

* Object 方法的返回值

* */

@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;

}

}

JDK動態代理測試:

/**

* JDK動態代理測試類

*/

public static void main(String[] args) {

Car car = new Car();

InvocationHandler h = new TimeHandler(car);

Clas s<?> cls = car.getClass();

/**

* loader 類加載器

* interfaces 實現接口

* h InvocationHandler

*/

Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),

cls.getInterfaces(), h);

m.move();

}

總結:

動態代理實現步驟

1.創建一個實現接口InvocationHandler的類,它

必須實現i nvoke方法

2.創建被代理的類以及接口

3.調用Proxy的靜態方法,創建一個代理類

newProxyInstance(ClassLoader loader,Class[]

interfaces,InvocationHandler h)

4.通過代理調用方法

動態代理實現思路

實現功能: 通過Proxy的newProxyInstance返回代理對象

1、聲明一段源碼(動態產生代理)

2、編譯源碼(JDK Compiler API),產生新的類(代理類)

3、將這個類load到內存當中,產生一個新的對象(代理對象)

4、return 代理對象

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章