靜態(tài)代理和動(dòng)態(tài)代理,什么場(chǎng)景使用?

靜態(tài)代理類(lèi):

  • 由程序員創(chuàng)建或由特定工具自動(dòng)生成源代碼,再對(duì)其編譯。在程序運(yùn)行前,代理類(lèi)的.class文件就已經(jīng)存在了。

動(dòng)態(tài)代理類(lèi):

  • 在程序運(yùn)行時(shí),運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成。
    場(chǎng)景先舉個(gè)例子:
    假如你是一個(gè)大房東(被代理人),你有很多套房子想要出租,而你覺(jué)得找租客太麻煩,不愿意自己弄,因而你找一個(gè)人來(lái)代理你(代理人),幫打理這些東西,而這個(gè)人(代理人也就是中介)在幫你出租房屋的時(shí)候?qū)δ闶杖∫恍┫鄳?yīng)的中介費(fèi)(對(duì)房屋出租的一些額外操作)。對(duì)于租客而言,中介就是房東,代理你做一些事情。
    以上,就是一個(gè)代理的例子,而他為什么叫動(dòng)態(tài)代理,“動(dòng)態(tài)”兩個(gè)字體現(xiàn)在什么地方?
    我們可以這樣想,如果你的每一套房子你都請(qǐng)一個(gè)代理人幫你打理,每當(dāng)你想再出租一套房子的時(shí)候你得再請(qǐng)一個(gè),這樣你會(huì)請(qǐng)很多的代理人,花費(fèi)高額的中介成本,這可以看作常說(shuō)的“靜態(tài)代理”。
    但假如我們把所有的房子都交給一個(gè)中介來(lái)代理,讓他在多套房子之間動(dòng)態(tài)的切換身份,幫你應(yīng)付每一個(gè)租客。這就是一個(gè)“動(dòng)態(tài)代理”的過(guò)程。動(dòng)態(tài)代理的一大特點(diǎn)就是編譯階段沒(méi)有代理類(lèi)在運(yùn)行時(shí)才生成代理類(lèi)。
房屋出租的操作
/**
*定義一個(gè)借口   
**/
public interface RentHouse {
void rent();//房屋出租
void charge(String str);//出租費(fèi)用收取
}
房東
public class HouseOwner implements RentHouse {
public void rent() {
    System.out.println("I want to rent my house");
}

public void charge(String str) {
    System.out.println("You get : " + str + " RMB HouseCharge.");
}
}
中介
public class DynamicProxy implements InvocationHandler {

// 這個(gè)就是我們要代理的真實(shí)對(duì)象,即房東
private Object subject;

//  構(gòu)造方法,給我們要代理的真實(shí)對(duì)象賦初值
public DynamicProxy(Object subject) {
    this.subject = subject;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //  在代理真實(shí)對(duì)象前我們可以添加一些自己的操作,中介收取中介費(fèi)
    System.out.println("before "+method.getName()+" house");

    System.out.println("Method:" + method.getName());

    //        如果方法是 charge 則中介收取100元中介費(fèi)
    if (method.getName().equals("charge")) {

        method.invoke(subject, args);
        System.out.println("I will get 100 RMB ProxyCharge.");

    } else {
        //    當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來(lái)進(jìn)行調(diào)用
        method.invoke(subject, args);
    }

    //  在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作
    System.out.println("after "+method.getName()+" house");

    return null;
}
}
客人
public class Client {
public static void main(String[] args)
{
    //    我們要代理的真實(shí)對(duì)象--房東
    HouseOwner houseOwner = new HouseOwner();

    //    我們要代理哪個(gè)真實(shí)對(duì)象,就將該對(duì)象傳進(jìn)去,最后是通過(guò)該真實(shí)對(duì)象來(lái)調(diào)用其方法的
    InvocationHandler handler = new DynamicProxy(houseOwner);

    /*
     * 通過(guò)Proxy的newProxyInstance方法來(lái)創(chuàng)建我們的代理對(duì)象,我們來(lái)看看其三個(gè)參數(shù)
     * 第一個(gè)參數(shù) handler.getClass().getClassLoader() ,我們這里使用handler這個(gè)類(lèi)的ClassLoader對(duì)象來(lái)加載我們的代理對(duì)象
     * 第二個(gè)參數(shù)realSubject.getClass().getInterfaces(),我們這里為代理對(duì)象提供的接口是真實(shí)對(duì)象所實(shí)行的接口,表示我要代理的是該真實(shí)對(duì)象,這樣我就能調(diào)用這組接口中的方法了
     * 第三個(gè)參數(shù)handler, 我們這里將這個(gè)代理對(duì)象關(guān)聯(lián)到了上方的 InvocationHandler 這個(gè)對(duì)象上
     */
    RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner
            .getClass().getInterfaces(), handler);//一個(gè)動(dòng)態(tài)代理類(lèi),中介

    System.out.println(rentHouse.getClass().getName());
    rentHouse.rent();
    rentHouse.charge("10000");
}
}
輸出結(jié)果
com.sun.proxy.$Proxy0
before rent house
Method:rent
I want to rent my house
after rent house
before charge house
Method:charge
You get : 10000 RMB HouseCharge.
I will get 100 RMB ProxyCharge.
after charge house

Process finished with exit code 0
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容