欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

這篇文章將為大家詳細(xì)講解有關(guān)Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

豐順ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書(shū)合作)期待與您的合作!

面試問(wèn)題:Java里的代理設(shè)計(jì)模式(Proxy Design Pattern)一共有幾種實(shí)現(xiàn)方式?這個(gè)題目很像孔乙己?jiǎn)枴败钕愣沟能钭钟心膸追N寫(xiě)法?”

所謂代理模式,是指客戶端(Client)并不直接調(diào)用實(shí)際的對(duì)象(下圖右下角的RealSubject),而是通過(guò)調(diào)用代理(Proxy),來(lái)間接的調(diào)用實(shí)際的對(duì)象。

代理模式的使用場(chǎng)合,一般是由于客戶端不想直接訪問(wèn)實(shí)際對(duì)象,或者訪問(wèn)實(shí)際的對(duì)象存在技術(shù)上的障礙,因而通過(guò)代理對(duì)象作為橋梁,來(lái)完成間接訪問(wèn)。

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

實(shí)現(xiàn)方式一:靜態(tài)代理

開(kāi)發(fā)一個(gè)接口IDeveloper,該接口包含一個(gè)方法writeCode,寫(xiě)代碼。

public interface IDeveloper {

     public void writeCode();

}

創(chuàng)建一個(gè)Developer類,實(shí)現(xiàn)該接口。

public class Developer implements IDeveloper{
    private String name;
    public Developer(String name){
        this.name = name;
    }
    @Override
    public void writeCode() {
        System.out.println("Developer " + name + " writes code");
    }
}

測(cè)試代碼:創(chuàng)建一個(gè)Developer實(shí)例,名叫Jerry,去寫(xiě)代碼!

public class DeveloperTest {
    public static void main(String[] args) {
        IDeveloper jerry = new Developer("Jerry");
        jerry.writeCode();
    }
}

現(xiàn)在問(wèn)題來(lái)了。Jerry的項(xiàng)目經(jīng)理對(duì)Jerry光寫(xiě)代碼,而不維護(hù)任何的文檔很不滿。假設(shè)哪天Jerry休假去了,其他的程序員來(lái)接替Jerry的工作,對(duì)著陌生的代碼一臉問(wèn)號(hào)。經(jīng)全組討論決定,每個(gè)開(kāi)發(fā)人員寫(xiě)代碼時(shí),必須同步更新文檔。

為了強(qiáng)迫每個(gè)程序員在開(kāi)發(fā)時(shí)記著寫(xiě)文檔,而又不影響大家寫(xiě)代碼這個(gè)動(dòng)作本身, 我們不修改原來(lái)的Developer類,而是創(chuàng)建了一個(gè)新的類,同樣實(shí)現(xiàn)IDeveloper接口。這個(gè)新類DeveloperProxy內(nèi)部維護(hù)了一個(gè)成員變量,指向原始的IDeveloper實(shí)例:

public class DeveloperProxy implements IDeveloper{
    private IDeveloper developer;
    public DeveloperProxy(IDeveloper developer){
        this.developer = developer;
    }
    @Override
    public void writeCode() {
        System.out.println("Write documentation...");
        this.developer.writeCode();
    }
}

這個(gè)代理類實(shí)現(xiàn)的writeCode方法里,在調(diào)用實(shí)際程序員writeCode方法之前,加上一個(gè)寫(xiě)文檔的調(diào)用,這樣就確保了程序員寫(xiě)代碼時(shí)都伴隨著文檔更新。

測(cè)試代碼:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

靜態(tài)代理方式的優(yōu)點(diǎn)

1. 易于理解和實(shí)現(xiàn)

2. 代理類和真實(shí)類的關(guān)系是編譯期靜態(tài)決定的,和下文馬上要介紹的動(dòng)態(tài)代理比較起來(lái),執(zhí)行時(shí)沒(méi)有任何額外開(kāi)銷。

靜態(tài)代理方式的缺點(diǎn)

每一個(gè)真實(shí)類都需要一個(gè)創(chuàng)建新的代理類。還是以上述文檔更新為例,假設(shè)老板對(duì)測(cè)試工程師也提出了新的要求,讓測(cè)試工程師每次測(cè)出bug時(shí),也要及時(shí)更新對(duì)應(yīng)的測(cè)試文檔。那么采用靜態(tài)代理的方式,測(cè)試工程師的實(shí)現(xiàn)類ITester也得創(chuàng)建一個(gè)對(duì)應(yīng)的ITesterProxy類。

public interface ITester {
    public void doTesting();
}
Original tester implementation class:
public class Tester implements ITester {
    private String name;
    public Tester(String name){
        this.name = name;
    }
    @Override
    public void doTesting() {
        System.out.println("Tester " + name + " is testing code");
    }
}
public class TesterProxy implements ITester{
    private ITester tester;
    public TesterProxy(ITester tester){
        this.tester = tester;
    }
    @Override
    public void doTesting() {
        System.out.println("Tester is preparing test documentation...");
        tester.doTesting();
    }
}

正是因?yàn)橛辛遂o態(tài)代碼方式的這個(gè)缺點(diǎn),才誕生了Java的動(dòng)態(tài)代理實(shí)現(xiàn)方式。

Java動(dòng)態(tài)代理實(shí)現(xiàn)方式一:InvocationHandler

InvocationHandler的原理我曾經(jīng)專門(mén)寫(xiě)文章介紹過(guò):Java動(dòng)態(tài)代理之InvocationHandler最簡(jiǎn)單的入門(mén)教程

通過(guò)InvocationHandler, 我可以用一個(gè)EnginnerProxy代理類來(lái)同時(shí)代理Developer和Tester的行為。

public class EnginnerProxy implements InvocationHandler {
    Object obj;
    public Object bind(Object obj)
    {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
        .getClass().getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable
    {
        System.out.println("Enginner writes document");
        Object res = method.invoke(obj, args);
        return res;
    }
}

真實(shí)類的writeCode和doTesting方法在動(dòng)態(tài)代理類里通過(guò)反射的方式進(jìn)行執(zhí)行。

測(cè)試輸出:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

通過(guò)InvocationHandler實(shí)現(xiàn)動(dòng)態(tài)代理的局限性

假設(shè)有個(gè)產(chǎn)品經(jīng)理類(ProductOwner) 沒(méi)有實(shí)現(xiàn)任何接口。

public class ProductOwner {
    private String name;
    public ProductOwner(String name){
        this.name = name;
    }
    public void defineBackLog(){
        System.out.println("PO: " + name + " defines Backlog.");
    }
}

我們?nèi)匀徊扇nginnerProxy代理類去代理它,編譯時(shí)不會(huì)出錯(cuò)。運(yùn)行時(shí)會(huì)發(fā)生什么事?

ProductOwner po = new ProductOwner("Ross");

ProductOwner poProxy = (ProductOwner) new EnginnerProxy().bind(po);

poProxy.defineBackLog();

運(yùn)行時(shí)報(bào)錯(cuò)。所以局限性就是:如果被代理的類未實(shí)現(xiàn)任何接口,那么不能采用通過(guò)InvocationHandler動(dòng)態(tài)代理的方式去代理它的行為。

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

Java動(dòng)態(tài)代理實(shí)現(xiàn)方式二:CGLIB

CGLIB是一個(gè)Java字節(jié)碼生成庫(kù),提供了易用的API對(duì)Java字節(jié)碼進(jìn)行創(chuàng)建和修改。關(guān)于這個(gè)開(kāi)源庫(kù)的更多細(xì)節(jié),請(qǐng)移步至CGLIB在github上的倉(cāng)庫(kù):https://github.com/cglib/cglib

我們現(xiàn)在嘗試用CGLIB來(lái)代理之前采用InvocationHandler沒(méi)有成功代理的ProductOwner類(該類未實(shí)現(xiàn)任何接口)。

現(xiàn)在我改為使用CGLIB API來(lái)創(chuàng)建代理類:

public class EnginnerCGLibProxy {
    Object obj;
    public Object bind(final Object target)
    {
        this.obj = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable
            {
                System.out.println("Enginner 2 writes document");
                Object res = method.invoke(target, args);
                return res;
            }
        }
        );
        return enhancer.create();
    }
}

測(cè)試代碼:

ProductOwner ross = new ProductOwner("Ross");

ProductOwner rossProxy = (ProductOwner) new EnginnerCGLibProxy().bind(ross);

rossProxy.defineBackLog();

盡管ProductOwner未實(shí)現(xiàn)任何代碼,但它也成功被代理了:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

用CGLIB實(shí)現(xiàn)Java動(dòng)態(tài)代理的局限性

如果我們了解了CGLIB創(chuàng)建代理類的原理,那么其局限性也就一目了然。我們現(xiàn)在做個(gè)實(shí)驗(yàn),將ProductOwner類加上final修飾符,使其不可被繼承:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

再次執(zhí)行測(cè)試代碼,這次就報(bào)錯(cuò)了: Cannot subclass final class XXXX。

所以通過(guò)CGLIB成功創(chuàng)建的動(dòng)態(tài)代理,實(shí)際是被代理類的一個(gè)子類。那么如果被代理類被標(biāo)記成final,也就無(wú)法通過(guò)CGLIB去創(chuàng)建動(dòng)態(tài)代理。

Java動(dòng)態(tài)代理實(shí)現(xiàn)方式三:通過(guò)編譯期提供的API動(dòng)態(tài)創(chuàng)建代理類

假設(shè)我們確實(shí)需要給一個(gè)既是final,又未實(shí)現(xiàn)任何接口的ProductOwner類創(chuàng)建動(dòng)態(tài)代碼。除了InvocationHandler和CGLIB外,我們還有最后一招:

我直接把一個(gè)代理類的源代碼用字符串拼出來(lái),然后基于這個(gè)字符串調(diào)用JDK的Compiler(編譯期)API,動(dòng)態(tài)的創(chuàng)建一個(gè)新的.java文件,然后動(dòng)態(tài)編譯這個(gè).java文件,這樣也能得到一個(gè)新的代理類。

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

測(cè)試成功:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

我拼好了代碼類的源代碼,動(dòng)態(tài)創(chuàng)建了代理類的.java文件,能夠在Eclipse里打開(kāi)這個(gè)用代碼創(chuàng)建的.java文件,

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

下圖是如何動(dòng)態(tài)創(chuàng)建ProductPwnerSCProxy.java文件:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

下圖是如何用JavaCompiler API動(dòng)態(tài)編譯前一步動(dòng)態(tài)創(chuàng)建出的.java文件,生成.class文件:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

下圖是如何用類加載器加載編譯好的.class文件到內(nèi)存:

Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)

關(guān)于Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

文章名稱:Java中靜態(tài)代理和動(dòng)態(tài)代理有哪四種方法實(shí)現(xiàn)
文章地址:http://aaarwkj.com/article48/pegjep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、靜態(tài)網(wǎng)站、網(wǎng)站改版、網(wǎng)站導(dǎo)航、微信公眾號(hào)做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化
亚洲国产成人一区二区精品区| 欧美性做爰片免费视频网| 欧美黄色日本一区二区| 一区二区三区av夏目彩春| 特级艳片在线观看免费| 日本免费精品人成视频| 国产在线成年人免费观看| 顶级少妇做爰片高潮丸| 亚洲日本成人av在线观看| 韩日av一区二区三区| 久久这里只有精品蜜桃| 亚洲av最近在线观看| 一区二区三区高清av在线| 一区二区三区都市激情| 久久尤物av天堂日日综合| 91精品国产老熟女在线| 亚洲国产视频不卡一区| 日韩精品一区中文字幕在线| 亚洲欧美国产日韩天堂区| 亚洲午夜精品久久久天堂| av电影在线中文字幕| 大屁股白浆一区二区三区| 91麻豆粉色视频在线| 另类视频网站在线观看| 青青草原天堂在线免费观看| 四虎免费在线高清观看| 夫妻性生活视频全过程| 国产精品一区二区毛卡片| 欧美av在线免费观看| 国产99久久精品免费看| 日韩在线不卡视频一区| 97视频网站在线观看| 麻豆人妻少妇精品毛片| 黄色大片免费在线观看| 国产中文字幕有码视频| 国产精品毛片一区内射| 日本在线观看免费高清| 男女性生活视频成年人观看| 中文字幕精品人妻在线| 亚洲欧美成人免费视频| 亚洲av一区二区三区网站|