Java 深入淺出講解代理模式
1、動(dòng)態(tài)代理模式
動(dòng)態(tài)代理的特點(diǎn):
- 當(dāng)代理對(duì)象的時(shí)候,不需要實(shí)現(xiàn)接口
- 代理對(duì)象的生成,是利用JDK的API,動(dòng)態(tài)的在內(nèi)存中構(gòu)建代理對(duì)象(需要我們指定創(chuàng)建代理對(duì)象/目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類型)
動(dòng)態(tài)代理的別稱:JDK代理、接口代理
2、JDK動(dòng)態(tài)代理
類圖:

Java動(dòng)態(tài)代理類位于java.lang.reflect包下
一般主要涉及到以下兩個(gè)類:
1、Interface InvocationHandler : 該接口中僅定義了一個(gè)方法public object invoke(Object obj,Method method, Object[] args) 在實(shí)際使用時(shí),第一個(gè)參數(shù)obj一般是指代理類,method是被代理的方法,args為該方法的參數(shù)數(shù)組。這個(gè)抽象方法在代理類中動(dòng)態(tài)實(shí)現(xiàn)。
2、Proxy:該類即為動(dòng)態(tài)代理類
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h):
返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用(可使用被代理類的在接口中聲明過(guò)的方法)
動(dòng)態(tài)代的實(shí)現(xiàn)步驟:
- 創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類,它必須實(shí)現(xiàn)invoke方法
- 創(chuàng)建被代理的類以及接口
- 調(diào)用Proxy的靜態(tài)方法,創(chuàng)建一個(gè)代理類:
newProxyInstance(ClassLoader loader,Class[] - 通過(guò)代理調(diào)用方法
3、JDK動(dòng)態(tài)代理代碼演示
比如現(xiàn)在有一個(gè)汽車駕駛的方法:
public interface Moveable {
void move();
}
現(xiàn)在有一輛汽車:
//實(shí)現(xiàn)Moveable 接口,并隨機(jī)暫停一段時(shí)間
import java.util.Random;
public class Car implements Moveable{
@Override
public void move() {
try{
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽車行駛中");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
時(shí)間代理類:
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;
/**
*
* @param proxy :被代理的對(duì)象
* @param method:被代理對(duì)象的方法
* @param args:方法的參數(shù)
* @return
* @throws Throwable
* 返回值: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("汽車行駛結(jié)束,行駛的時(shí)間為:"+(endTime-startTime)+"毫秒");
return null;
}
}
測(cè)試類:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();
/**
* newProxyInstanced的參數(shù)
* 分別是:類加載器、實(shí)現(xiàn)的接口、實(shí)現(xiàn)的處理器
*/
Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(),h);
m.move();
}
}
這樣的輸出結(jié)果是:
汽車開始行使
汽車行駛中
汽車行駛結(jié)束,行駛的時(shí)間為:137毫秒
//后面的時(shí)間是隨機(jī)產(chǎn)生的,每次都不一樣
注意:
JDK代理只能代理實(shí)現(xiàn)了接口的類,沒有實(shí)現(xiàn)接口的不能代理

以上就是JDK動(dòng)態(tài)代理,當(dāng)然還有cglib動(dòng)態(tài)代理:
cglib是針對(duì)類來(lái)實(shí)現(xiàn)代理的,cglib的原理是對(duì)指定的目標(biāo)類生成一個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類進(jìn)行代理,因?yàn)樾?yīng)學(xué)長(zhǎng)自己對(duì)這一塊也沒有完全掌握,這里就不多講解,大家可以參考其他博主的技術(shù)文章。
三月份完美收官!最后小應(yīng)學(xué)長(zhǎng)十分感謝大家的支持的陪伴,你們?cè)谥С质俏易畲蟮膭?dòng)力,繼續(xù)寫出大家喜歡的文章!
到此這篇關(guān)于Java 深入淺出講解代理模式的文章就介紹到這了,更多相關(guān)Java 代理模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java selenium教程之selenium詳細(xì)介紹
本文主要介紹Java selenium,這里整理了selenium的一些基本資料,此軟件主要用于Web UI自動(dòng)測(cè)試框架,有興趣的同學(xué)可以看一下2016-08-08
Java集合Map的clear與new Map區(qū)別詳解
這篇文章主要介紹了Java集合Map的clear與new Map區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
Java通過(guò)cellstyle屬性設(shè)置Excel單元格常用樣式的全面總結(jié)講解
在處理Excel文件時(shí),經(jīng)常需要對(duì)單元格進(jìn)行樣式設(shè)置,以滿足特定的需求和美化要求,這篇文章主要給大家介紹了關(guān)于Java通過(guò)cellstyle屬性設(shè)置Excel單元格常用樣式的相關(guān)資料,需要的朋友可以參考下2024-01-01

