国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

java設(shè)計(jì)模式之動(dòng)態(tài)代理

piglei / 2201人閱讀

摘要:場景描述病從口入這句成語告訴我們注意飲食健康,小六同學(xué)想吃蘋果,在吃蘋果之前需要清洗一下蘋果和洗一下手,吃完蘋果后,需要洗一下手保持個(gè)人衛(wèi)生十分鐘后。。。動(dòng)態(tài)代理小六委托管家來代理洗食物和洗手,小六屬于委托對(duì)象,管家屬于代理對(duì)象。

前言

為了更好的理解代理模式,首先根據(jù)生活中實(shí)際場景進(jìn)行模擬,讓我們?cè)谏钪腥ンw驗(yàn)設(shè)計(jì)思想的美妙。

場景描述

“病從口入”這句成語告訴我們注意飲食健康,小六同學(xué)想吃蘋果,在吃蘋果之前需要清洗一下蘋果和洗一下手,吃完蘋果后,需要洗一下手保持個(gè)人衛(wèi)生;十分鐘后。。。小六同學(xué)又想吃一個(gè)大鴨梨,清洗鴨梨--洗手--吃鴨梨--吃完洗手。

代碼模擬

蘋果和鴨梨都屬于食物,創(chuàng)建一個(gè)食物接口

public interface Foods {
    void eatApple();
    void eatpear();
}

小六同學(xué)吃蘋果和鴨梨的動(dòng)作,相當(dāng)于實(shí)現(xiàn)類

public class People implements Foods {
    @Override
    public void eatApple() {
        System.out.println("eat apple");
    }
    @Override
    public void eatpear() {
        System.out.println("eat pear");
    }
}

小六同學(xué)謹(jǐn)記“病從口入”這句成語,所以在吃食物之前需要清洗食物洗手,吃完食物后需要洗手。so easy~~直接在People實(shí)現(xiàn)類上加上這兩個(gè)動(dòng)作就可以,但是小五同學(xué)說我吃蘋果和鴨梨之前只洗手不洗食物,為了實(shí)現(xiàn)小五這個(gè)動(dòng)作需要重新寫接口,重寫實(shí)現(xiàn)類。那可不可以在不改變實(shí)現(xiàn)類的前提下實(shí)現(xiàn)呢,答案是肯定的,那就用到靜態(tài)代理來實(shí)現(xiàn)。

 public static void main(String []args){
        People people = new Perople();
        System.out.println("吃前:洗食物洗手");
        people.eatApple();
        System.out.println("吃后:洗手");
        System.out.println("吃前:洗食物洗手");
        people.eatpear();
        System.out.println("吃后:洗手");
    }
小六變胖了

小六同學(xué)最近變胖了,原因是越來越能吃了,一天需要吃蘋果、鴨梨、香蕉、櫻桃、橘子、橙子。。。等一百種水果才能吃飽!雖然飲食控制不住,但小六同學(xué)還是每次吃食物之前都洗食物洗手,吃完食物后洗手的好習(xí)慣,隨之食量的增大,每次都需要洗食物洗手,費(fèi)力費(fèi)時(shí)間,小六心生一計(jì),不如干脆找個(gè)管家,每次想吃東西時(shí)只需喊一聲,管家?guī)兔ο词澄锵词郑约褐回?fù)責(zé)吃,棒極了。

動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式

Java 實(shí)現(xiàn)動(dòng)態(tài)代理有兩種方式,一種是 Java 自帶的 JDK 動(dòng)態(tài)代理,還有一種是使用字節(jié)碼增強(qiáng)技術(shù)實(shí)現(xiàn)的 CGLIB 庫動(dòng)態(tài)代理。

兩種方法同時(shí)存在,各有優(yōu)劣。jdk動(dòng)態(tài)代理是由Java內(nèi)部的反射機(jī)制來實(shí)現(xiàn)的,cglib動(dòng)態(tài)代理底層則是借助asm來實(shí)現(xiàn)的。總的來說,反射機(jī)制在生成類的過程中比較高效,而asm在生成類之后的相關(guān)執(zhí)行過程中比較高效(可以通過將asm生成的類進(jìn)行緩存,這樣解決asm生成類過程低效問題)。還有一點(diǎn)必須注意:jdk動(dòng)態(tài)代理的應(yīng)用前提,必須是目標(biāo)類基于統(tǒng)一的接口。如果沒有上述前提,jdk動(dòng)態(tài)代理不能應(yīng)用。由此可以看出,jdk動(dòng)態(tài)代理有一定的局限性,cglib這種第三方類庫實(shí)現(xiàn)的動(dòng)態(tài)代理應(yīng)用更加廣泛,且在效率上更有優(yōu)勢。

JDK動(dòng)態(tài)代理

小六委托管家來代理洗食物和洗手,小六屬于委托對(duì)象,管家屬于代理對(duì)象。

JDK動(dòng)態(tài)代理主要兩個(gè)相關(guān)類:

Proxy(java.lang.reflect包下的),主要負(fù)責(zé)管理和創(chuàng)建代理類的工作。

InvocationHandler 接口,只擁有一個(gè)invoke方法,主要負(fù)責(zé)方法調(diào)用部分,是動(dòng)態(tài)代理中我們需要實(shí)現(xiàn)的方法

每一個(gè)代理實(shí)例都必須要實(shí)現(xiàn)InvocationHandler這個(gè)接口,當(dāng)我們通過代理對(duì)象調(diào)用一個(gè)方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)為由InvocationHandler這個(gè)接口的 invoke 方法來進(jìn)行調(diào)用,所以要想對(duì)方法(吃食物)加強(qiáng)(洗食物洗手)就需要在invoke方法中實(shí)現(xiàn)。

public class FoodsHandler implements InvocationHandler{
    private Object object;//委托對(duì)象(小六同學(xué))
    public FoodsHandler(Object object){
        this.object = object;
    }
    /*invoke方法的三個(gè)參數(shù):
    proxy:  指代我們所代理的那個(gè)真實(shí)對(duì)象
    method:  指代的是我們所要調(diào)用真實(shí)對(duì)象的某個(gè)方法的Method對(duì)象
    args:  指代的是調(diào)用真實(shí)對(duì)象某個(gè)方法時(shí)接受的參數(shù)
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        System.out.println("吃前:洗食物洗手");
          //當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),會(huì)自動(dòng)跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來進(jìn)行調(diào)用
        Object result = method.invoke(object, args);
        System.out.println("吃后:洗手");
        return result;
    }
}
public static void main(String []args){
        //委托對(duì)象(小六同學(xué))
        People people = new People();
          //我們要代理哪個(gè)真實(shí)對(duì)象,就將該對(duì)象傳進(jìn)去,最后是通過該真實(shí)對(duì)象來調(diào)用其方法的
        FoodsHandler inter = new FoodsHandler(people);
        //加上這句將會(huì)產(chǎn)生一個(gè)$Proxy0.class文件,這個(gè)文件即為動(dòng)態(tài)生成的代理類文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        //獲取代理類實(shí)例foods
        Foods foods = (Foods)(Proxy.newProxyInstance(Foods.class.getClassLoader(), new                 Class[] {Foods.class}, fh));

        //通過代理類對(duì)象調(diào)用代理類方法,實(shí)際上會(huì)轉(zhuǎn)到invoke方法調(diào)用
        foods.eatApple();
        foods.eatpear();
    }

/*newProxyInstance方法三個(gè)參數(shù)的解釋如下
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) throws IllegalArgumentException 
loader:一個(gè)ClassLoader對(duì)象,定義了由哪個(gè)ClassLoader對(duì)象來對(duì)生成的代理對(duì)象進(jìn)行加載
interfaces:一個(gè)Interface對(duì)象的數(shù)組,表示的是我將要給我需要代理的對(duì)象提供一組什么接口,如果我提供了一組接口給它,那么這個(gè)代理對(duì)象就宣稱實(shí)現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了
h:一個(gè)InvocationHandler對(duì)象,表示的是當(dāng)我這個(gè)動(dòng)態(tài)代理對(duì)象在調(diào)用方法的時(shí)候,會(huì)關(guān)聯(lián)到哪一個(gè)InvocationHandler對(duì)象上
*/
Cglib動(dòng)態(tài)代理

上面的 JDK 動(dòng)態(tài)代理需要定義一個(gè)接口,實(shí)現(xiàn)類實(shí)現(xiàn)接口中的方法,如果實(shí)現(xiàn)類不能實(shí)現(xiàn)接口時(shí),我們就需要 CGLIB 動(dòng)態(tài)代理。

使用 CGLIB 動(dòng)態(tài)代理之前需要導(dǎo)入相關(guān) jar 包,可以多帶帶導(dǎo)入 cglib-.jar 包和 asm-.jar 包,也可以只導(dǎo)入一個(gè) cglib-nodep-.jar 包(包含了 asm)。下載鏈接

public class People {
    public void eatApple() {
        System.out.println("eat apple");
    }

    public void eatpear() {
        System.out.println("eat pear");
    }
}
public class PeopleCglib implements MethodInterceptor {
    @Override
    // object 代表要增強(qiáng)的對(duì)象,method代表要攔截的方法,objects 代表方法中的參數(shù),methodProxy 代表對(duì)方法的代理
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable{
        System.out.println("吃前:洗食物洗手");
        methodProxy.invokeSuper(object,objects);
        System.out.println("吃后:洗手");
        return object;
    }
}
public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer(); // 增強(qiáng)類對(duì)象
        enhancer.setSuperclass(People.class); // 設(shè)置要增強(qiáng)的類(People)
        PeopleCglib peopleCglib = new PeopleCglib();
        enhancer.setCallback(peopleCglib); // 設(shè)置要增強(qiáng)的方法(peopleCglib)
        People people = (People) enhancer.create(); // 生成增強(qiáng)過的子類對(duì)象
        people.eatApple(); // 調(diào)用方法實(shí)際為增強(qiáng)過的方法
        people.eatApple();
    }
}

輸出結(jié)果

吃前:洗食物洗手
eat apple
吃后:洗手
吃前:洗食物洗手
eat apple
吃后:洗手

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/75363.html

相關(guān)文章

  • Java設(shè)計(jì)模式代理模式

    摘要:設(shè)計(jì)模式之代理模式今天學(xué)到的動(dòng)態(tài)代理實(shí)現(xiàn),對(duì)代理這個(gè)概念很模糊,看了一篇文章發(fā)現(xiàn)這是一種設(shè)計(jì)模式,于是學(xué)習(xí)記錄一下。簡介代理模式是一種對(duì)象結(jié)構(gòu)型的模式,主要為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。下面依次講解著三種代理。 設(shè)計(jì)模式之代理模式 今天學(xué)到Spring的動(dòng)態(tài)代理實(shí)現(xiàn)AOP,對(duì)代理這個(gè)概念很模糊,看了一篇文章發(fā)現(xiàn)這是一種設(shè)計(jì)模式,于是學(xué)習(xí)記錄一下。 簡介 代理模式是一種對(duì)...

    ZHAO_ 評(píng)論0 收藏0
  • 慕課網(wǎng)_《模式的秘密代理模式》學(xué)習(xí)總結(jié)

    時(shí)間:2017年08月28日星期一說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:https://github.com/zccodere/s...學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:代理模式 1-1 概念介紹 學(xué)習(xí)本課程基礎(chǔ) 面向?qū)ο蟮脑O(shè)計(jì)思維 了解多態(tài)的概念 了解反射機(jī)制 課程目標(biāo) 代理模式基本概念及分類...

    wow_worktile 評(píng)論0 收藏0
  • Java動(dòng)態(tài)代理InvocationHandler最簡單的入門教程

    摘要:網(wǎng)上關(guān)于的動(dòng)態(tài)代理,和這些概念有講解得非常高深的文章。現(xiàn)在咱們通過一個(gè)最簡單的例子認(rèn)識(shí)什么是。創(chuàng)建一個(gè)簡單的類,實(shí)現(xiàn)這個(gè)接口。看看用如何優(yōu)雅實(shí)現(xiàn)吧希望這個(gè)例子能讓大家對(duì)的動(dòng)態(tài)代理之有了最基本的了解。 網(wǎng)上關(guān)于Java的動(dòng)態(tài)代理,Proxy和InvocationHandler這些概念有講解得非常高深的文章。其實(shí)這些概念沒有那么復(fù)雜。現(xiàn)在咱們通過一個(gè)最簡單的例子認(rèn)識(shí)什么是Invocatio...

    lingdududu 評(píng)論0 收藏0
  • Java動(dòng)態(tài)代理InvocationHandler最簡單的入門教程

    摘要:網(wǎng)上關(guān)于的動(dòng)態(tài)代理,和這些概念有講解得非常高深的文章。現(xiàn)在咱們通過一個(gè)最簡單的例子認(rèn)識(shí)什么是。創(chuàng)建一個(gè)簡單的類,實(shí)現(xiàn)這個(gè)接口。看看用如何優(yōu)雅實(shí)現(xiàn)吧希望這個(gè)例子能讓大家對(duì)的動(dòng)態(tài)代理之有了最基本的了解。 網(wǎng)上關(guān)于Java的動(dòng)態(tài)代理,Proxy和InvocationHandler這些概念有講解得非常高深的文章。其實(shí)這些概念沒有那么復(fù)雜。現(xiàn)在咱們通過一個(gè)最簡單的例子認(rèn)識(shí)什么是Invocatio...

    Joonas 評(píng)論0 收藏0
  • 給女朋友講解什么是代理模式

    摘要:受知乎文章和設(shè)計(jì)模式之禪的啟發(fā),我也來搞一篇腦洞小開的文章由標(biāo)題可知,這篇文章是寫給我女朋友看的。于是這就讓經(jīng)紀(jì)人對(duì)粉絲說只有萬,我才會(huì)寫代碼。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個(gè)門了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡簡單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下...

    stormgens 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<