日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试官 | 说一下什么是代理模式?

發(fā)布時間:2025/3/11 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试官 | 说一下什么是代理模式? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

看了這篇文章,你會對靜態(tài)代理模式,JDK 動態(tài)代理模式和 CGLIB 動態(tài)代理模式有個很清晰的認(rèn)識。

01、簡介

  • 什么是代理模式

    代理模式也稱為委托模式,屬于結(jié)構(gòu)型模式之一。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標(biāo)對象之間起到中介的作用,比如我們生活中的郵局,快遞公司,婚介所等等。

  • 代理模式分類

    代理模式分為靜態(tài)代理模式和動態(tài)代理模式。

    靜態(tài)代理是由程序員創(chuàng)建或特定工具自動生成源代碼,再對其編譯。在程序運(yùn)行之前,代理類.class文件就已經(jīng)被創(chuàng)建了

    動態(tài)代理是在程序運(yùn)行時通過java反射機(jī)制動態(tài)創(chuàng)建的。

  • 代理模式的目的

    代理模式主要有兩個目的:一保護(hù)目標(biāo)對象,二增強(qiáng)目標(biāo)對象。

  • 02、靜態(tài)代理模式

    靜態(tài)代理模式的話我模擬一個古代結(jié)婚的場景。場景是這樣的:在古代,某家的公子看上了別家的姑娘,一般都是家里的大人去姑娘的家里提親,雙方父母同意了,然后就拜堂成婚,后面要宴請親朋好友。這里這個公子只需要拜堂成婚就行了,至于提親和宴請親友都是父母操辦的。我們用代碼來模擬一下這個場景。

    首先我們來建個 Person 接口:

    public interface Person {/*** 人有很對行為,這里我們用到的是結(jié)婚*/void marry(); }

    然后這家公子要成親,我們建個 Son 類實(shí)現(xiàn) Person 接口:

    public class Son implements Person {@Overridepublic void marry() {System.out.println("我終于結(jié)婚了");} }

    父親幫兒子提親,建個 Father 類:

    public class Father {private Son son;public Father(Son son){this.son = son;}public void marry(){System.out.println("父親上門提親");this.son.marry();System.out.println("父親宴請親友");} }

    最后是測試代碼:

    public class Test {public static void main(String[] args) {Father father = new Father(new Son());father.marry();} }

    輸出:

    父親上門提親 我終于結(jié)婚了 父親宴請親友

    代碼寫完了,大家有沒有發(fā)現(xiàn)靜態(tài)代理模式的一個缺點(diǎn)。那就是單一,一個類只能代理一個目標(biāo)對象。比如上面的場景,父親只能為自己的兒子提親,不能為別人家的孩子提親。

    下面我們來看看動態(tài)代理是怎么解決這個問題的。

    03、動態(tài)代理模式

    動態(tài)代理模式分為 JDK 動態(tài)代理和 cglib 動態(tài)代理兩種。這里先用 JDK 動態(tài)代理的方式來模擬一個通過婚介所找朋友的場景。

    先將 Person 接口改動下:

    public interface Person {/*** 找朋友*/void findFriend(); }

    然后是婚介所 JDKMatrimonialAgency 類:

    public class JDKMatrimonialAgency implements InvocationHandler {//被代理的對象,把引用給保存下來private Object target;public Object getInstance(Object target) throws Exception{this.target = target;Class<?> clazz = target.getClass();return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object obj = method.invoke(this.target,args);after();return obj;}private void before(){System.out.println("這里是婚介所,請?zhí)峁┠愕男枨?#34;);}private void after(){System.out.println("已經(jīng)找到合適的,盡快安排你相親");} }

    JDK 動態(tài)代理主要是實(shí)現(xiàn) InvocationHandler 接口,并實(shí)現(xiàn) invoke 方法

    然后創(chuàng)建 Customer 類:

    public class Customer implements Person {@Overridepublic void findFriend() {System.out.println("我要找一個胸大,腿長又好看的美女");} }

    最后測試類:

    public class Test {public static void main(String[] args) {try {Person obj = (Person)new JDKMatrimonialAgency().getInstance(new Customer());obj.findFriend();} catch (Exception e) {e.printStackTrace();}} }

    看下結(jié)果:

    這里是婚介所,請?zhí)峁┠愕男枨?我要找一個胸大,腿長又好看的美女 已經(jīng)找到合適的,盡快安排你相親

    然后我們用 CGLIB 來實(shí)現(xiàn),如果不是spring(spring已經(jīng)集成了 CGLIB )環(huán)境需要先引入 jar 包:

    <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version> </dependency>

    然后加一個 CglibMatrimonialAgency 類:

    public class CglibMatrimonialAgency implements MethodInterceptor {public Object getInstance(Class<?> clazz) throws Exception{Enhancer enhancer = new Enhancer();//要把哪個設(shè)置為即將生成的新類的父類enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)throws Throwable {//業(yè)務(wù)的增強(qiáng)before();Object obj = methodProxy.invokeSuper(o,objects);after();return obj;}private void before(){System.out.println("這里是婚介所,請?zhí)峁┠愕男枨?#34;);}private void after(){System.out.println("已經(jīng)找到合適的,盡快安排你相親");} }

    CGLIB 主要是實(shí)現(xiàn) MethodInterceptor 并實(shí)現(xiàn) intercept 方法。

    看下結(jié)果:

    這里是婚介所,請?zhí)峁┠愕男枨?我要找一個胸大,腿長又好看的美女 已經(jīng)找到合適的,盡快安排你相親

    04、JDK和CGLIB動態(tài)代理對比

  • JDK 動態(tài)代理是實(shí)現(xiàn)了被代理對象的接口,CGLib 是繼承了被代理對象。

  • JDK 和 CGLib 都是在運(yùn)行期生成字節(jié)碼,JDK 是直接寫 Class 字節(jié)碼,CGLib 使用 ASM框架寫 Class 字節(jié)碼,Cglib 代理實(shí)現(xiàn)更復(fù)雜,生成代理類比 JDK 效率低。

  • JDK 調(diào)用代理方法,是通過反射機(jī)制調(diào)用,CGLib 是通過 FastClass 機(jī)制直接調(diào)用方法,CGLib 執(zhí)行效率更高。

  • 05、代理模式的優(yōu)缺點(diǎn)

    優(yōu)點(diǎn):

  • 降低耦合度,擴(kuò)展性好

  • 代理對象將代理對象和目標(biāo)對象分離,起到保護(hù)目標(biāo)對象的作用

  • 可以對目標(biāo)對象的功能增強(qiáng)

  • 缺點(diǎn):

  • 增加類的數(shù)量

  • 因?yàn)闀{(diào)用增強(qiáng)方法,所以會造成處理速度慢

  • 增加了系統(tǒng)的復(fù)雜度(這是好的架構(gòu)都會有的缺點(diǎn),比如spring)

  • 近期熱文

    ?
    • 面試珍藏:最常見的200多道Java面試題

    • 被一個熟悉的面試題問懵了:String...

    • 面試官:如何實(shí)現(xiàn)冪等性校驗(yàn)?

    【END】

    關(guān)注下方二維碼,訂閱更多精彩內(nèi)容

    朕已閱?

    總結(jié)

    以上是生活随笔為你收集整理的面试官 | 说一下什么是代理模式?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。