最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中的三種代理模式詳解

 更新時(shí)間:2023年08月25日 11:34:48   作者:S_polygon  
這篇文章主要介紹了Java中的三種代理模式詳解,代理模式的關(guān)鍵點(diǎn)是:代理對(duì)象與目標(biāo)對(duì)象.代理對(duì)象是對(duì)目標(biāo)對(duì)象的擴(kuò)展,并會(huì)調(diào)用目標(biāo)對(duì)象,文中提供了部分代碼,需要的朋友可以參考下

Java代理模式

什么是代理模式?

代理(Proxy)是一種設(shè)計(jì)模式,為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。

代理模式的組成

  • 抽象角色:通過(guò)接口或抽象類(lèi)聲明真實(shí)角色實(shí)現(xiàn)的業(yè)務(wù)方法。
  • 代理角色:實(shí)現(xiàn)抽象角色,是真實(shí)角色的代理,通過(guò)真實(shí)角色的業(yè)務(wù)邏輯方法來(lái)實(shí)現(xiàn)抽象方法,并可以附加自己的操作。
  • 真實(shí)角色:實(shí)現(xiàn)抽象角色,定義真實(shí)角色所要實(shí)現(xiàn)的業(yè)務(wù)邏輯,供代理角色調(diào)用。

代理模式的優(yōu)點(diǎn)

(1).職責(zé)清晰

真實(shí)的角色就是實(shí)現(xiàn)實(shí)際的[業(yè)務(wù)邏輯,不用關(guān)心其他非本職責(zé)的事務(wù),通過(guò)后期的代理完成一件完成事務(wù),附帶的結(jié)果就是編程簡(jiǎn)潔清晰。

(2).代理對(duì)象可以在客戶(hù)端和目標(biāo)對(duì)象之間起到中介的作用,這樣起到了中介的作用和保護(hù)了目標(biāo)對(duì)象的作用。

(3).高擴(kuò)展性

代理模式的關(guān)鍵點(diǎn)是:代理對(duì)象與目標(biāo)對(duì)象.代理對(duì)象是對(duì)目標(biāo)對(duì)象的擴(kuò)展,并會(huì)調(diào)用目標(biāo)對(duì)象。

1、靜態(tài)代理

? 靜態(tài)代理在使用時(shí),需要定義接口或者父類(lèi),被代理對(duì)象與代理對(duì)象一起實(shí)現(xiàn)相同的接口或者是繼承相同父類(lèi)。

步驟1:創(chuàng)建UserDao.java接口

步驟2:創(chuàng)建UserDaoImpl.java(UserDao接口實(shí)現(xiàn)類(lèi))

步驟3:創(chuàng)建代理類(lèi)Proxy01.java(實(shí)現(xiàn)UserDao接口)

/**
 * 代理對(duì)象,靜態(tài)代理
 * */
public class Proxy01 implements UserDao {
    //接受保存目標(biāo)對(duì)象
    UserDao target;
    public Proxy01() {
    }
    public Proxy01(UserDao target) {
        this.target = target;
    }
    @Override
    public void getUser() {
        System.out.println("事務(wù)開(kāi)始");
        target.getUser();
        System.out.println("事務(wù)結(jié)束");
    }
}

步驟4:測(cè)試Proxy01_test.java

/**
 * 測(cè)試靜態(tài)代理
 * 靜態(tài)代理:修改被代理類(lèi)中的代理方法,需要修改代理類(lèi)中的方法
 * 缺點(diǎn):
 *
 * 因?yàn)榇韺?duì)象需要與目標(biāo)對(duì)象實(shí)現(xiàn)一樣的接口,所以會(huì)有很多代理類(lèi),類(lèi)太多.同時(shí),一旦接口增加方法,目標(biāo)對(duì)象與代理對(duì)象都要維護(hù).
 * */
public class Proxy01_test {
    public static void main(String[] args) {
        //目標(biāo)對(duì)象
        UserDao target = new UserDaoImpl();
        //代理對(duì)象,把目標(biāo)對(duì)象傳給代理對(duì)象,建立代理關(guān)系
        Proxy01 proxy = new Proxy01(target);
        proxy.getUser();//執(zhí)行的是代理的方法
    }
}

執(zhí)行結(jié)果:

在這里插入圖片描述

總結(jié):

  • 靜態(tài)代理在使用時(shí),需要定義接口或者父類(lèi),被代理對(duì)象與代理對(duì)象一起實(shí)現(xiàn)接口或繼承相同 的父類(lèi)

缺點(diǎn):

  • 因?yàn)榇韺?duì)象需要和被代理對(duì)象實(shí)現(xiàn)相同的接口或父類(lèi),所以會(huì)有太多的代理類(lèi)
  • 一旦接口中增加了方法后,被代理對(duì)象和代理對(duì)象都需要維護(hù)(非常麻煩,不方便)

2、jdk動(dòng)態(tài)代理

JDK中動(dòng)態(tài)代理類(lèi)只需要使用java.lang.reflect.Proxy.newProxyInstance方法,該方法需要接收三個(gè)參數(shù),完整的寫(xiě)法是:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

注意該方法是在Proxy類(lèi)中是靜態(tài)方法,且接收的三個(gè)參數(shù)依次為:

  • ClassLoader loader:指定當(dāng)前目標(biāo)對(duì)象使用類(lèi)加載器,獲取加載器的方法是固定的
  • Class<?>[] interfaces:目標(biāo)對(duì)象實(shí)現(xiàn)的接口類(lèi)型,使用泛型方式確認(rèn)類(lèi)型,獲取接口類(lèi)型的方法是固定的
  • InvocationHandler h;事件處理,執(zhí)行目標(biāo)對(duì)象的方法時(shí),會(huì)觸發(fā)事件處理器的方法,會(huì)把當(dāng)前執(zhí)行目標(biāo)對(duì)象的方法作為參數(shù)傳入

步驟1:創(chuàng)建UserDao.java接口

步驟2:創(chuàng)建UserDaoImpl.java(UserDao接口實(shí)現(xiàn)類(lèi))

步驟3:創(chuàng)建代理類(lèi)Proxy02.java

/**
 * jdk動(dòng)態(tài)代理類(lèi)
 * */
public class Proxy02 {
    //維護(hù)一個(gè)目標(biāo)對(duì)象
    private Object target;
    public Proxy02(Object target) {
        this.target = target;
    }
    //給目標(biāo)對(duì)象生成代理對(duì)象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this::invoke);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("開(kāi)始事務(wù)2");
        //執(zhí)行目標(biāo)對(duì)象方法
        Object returnValue = method.invoke(target, args);
        System.out.println("提交事務(wù)2");
        return returnValue;
    }
}

步驟4:測(cè)試Proxy02_test.java

/**
 * 測(cè)試jdk動(dòng)態(tài)代理
 * 代理對(duì)象不需要實(shí)現(xiàn)接口,但是目標(biāo)對(duì)象一定要實(shí)現(xiàn)接口,否則不能用動(dòng)態(tài)代理
 * 接口中增加方法時(shí)只用在實(shí)現(xiàn)類(lèi)中增加方法,不用修改代理類(lèi)。
 * */
public class Proxy02_test {
    public static void main(String[] args) {
        //目標(biāo)對(duì)象
        UserDao target = new UserDaoImpl();
        // 【原始的類(lèi)型 class top.polygon.proxy01.dao.impl.UserDaoImpl】
        System.out.println(target.getClass());
        // 給目標(biāo)對(duì)象,創(chuàng)建代理對(duì)象
        UserDao proxy = (UserDao) new Proxy02(target).getProxyInstance();
        // class $Proxy0   內(nèi)存中動(dòng)態(tài)生成的代理對(duì)象
        System.out.println(proxy.getClass());
        proxy.getUser();//執(zhí)行的是代理的方法
        proxy.insertUser();
    }
}

運(yùn)行結(jié)果:

在這里插入圖片描述

總結(jié):

代理對(duì)象不需要實(shí)現(xiàn)接口,但是目標(biāo)對(duì)象一定要實(shí)現(xiàn)接口,否則不能用動(dòng)態(tài)代理

3、cglib動(dòng)態(tài)代理

靜態(tài)代理和jdk動(dòng)態(tài)代理都要求目標(biāo)對(duì)象實(shí)現(xiàn)接口,

cglib動(dòng)態(tài)代理,使用以目標(biāo)對(duì)象子類(lèi)的方式實(shí)現(xiàn)代理,(當(dāng)目標(biāo)對(duì)象是一個(gè)單獨(dú)的對(duì)象,沒(méi)有實(shí)現(xiàn)任何接口時(shí)使用).

Cglib代理,也叫作子類(lèi)代理,它是在內(nèi)存中構(gòu)建一個(gè)子類(lèi)對(duì)象從而實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象功能的擴(kuò)展。Cglib是一個(gè)強(qiáng)大的高性能的代碼生成包,它可以在運(yùn)行期擴(kuò)展Java類(lèi)與實(shí)現(xiàn)Java接口。它廣泛的被許多AOP的框架使用,為其提供方法的interception(攔截),例如大家所熟知的Spring AOP。

? Cglib包的底層是通過(guò)使用一個(gè)小而快的字節(jié)碼處理框架ASM來(lái)轉(zhuǎn)換字節(jié)碼并生成新的類(lèi)。

Cglib子類(lèi)代理需要注意的是:

  • 需要引入cglib的jar包
  • 代理的類(lèi)不能是final,否則報(bào)錯(cuò)
  • 目標(biāo)對(duì)象的方法如果有final/static,那么不會(huì)被攔截,即不會(huì)執(zhí)行目標(biāo)對(duì)象額外的業(yè)務(wù)方法。

實(shí)現(xiàn)步驟:

步驟1:引入jar包

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

步驟2:創(chuàng)建被代理的類(lèi)UserDaoImpl.java

public class UserDaoImpl{
    public void getUser() {
        System.out.println("cglib動(dòng)態(tài)代理:得到用戶(hù)信息");
    }
    public void insertUser() {
        System.out.println("cglib動(dòng)態(tài)代理:添加用戶(hù)");
    }
}

步驟3:創(chuàng)建代理類(lèi)Proxy03.java

/**
 * cglib動(dòng)態(tài)代理
 *
 * */
public class Proxy03 implements MethodInterceptor {
    //維護(hù)目標(biāo)對(duì)象
    private Object target;
    public Proxy03(Object target) {
        this.target = target;
    }
    //給目標(biāo)對(duì)象創(chuàng)建一個(gè)代理對(duì)象
    public Object getProxyInstance(){
        //1.工具類(lèi)
        Enhancer en = new Enhancer();
        //2.設(shè)置父類(lèi)
        en.setSuperclass(target.getClass());
        //3.設(shè)置回調(diào)函數(shù)
        en.setCallback(this);
        //4.創(chuàng)建子類(lèi)(代理對(duì)象)
        return en.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("開(kāi)始事務(wù)...");
        //執(zhí)行目標(biāo)對(duì)象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("提交事務(wù)...");
        return returnValue;
    }
}

步驟4:測(cè)試Proxy03_test.java

public class Proxy03_test {
    public static void main(String[] args) {
        //目標(biāo)對(duì)象
        UserDao target = new UserDaoImpl();
        System.out.println(target.getClass());
        // 給目標(biāo)對(duì)象,創(chuàng)建代理對(duì)象
        UserDao proxy = (UserDao) new Proxy03(target).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.getUser();//執(zhí)行的是代理的方法
        proxy.insertUser();
    }
}

運(yùn)行結(jié)果

在這里插入圖片描述

到此這篇關(guān)于Java中的三種代理模式詳解的文章就介紹到這了,更多相關(guān)Java代理模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 緩存框架 Caffeine 應(yīng)用場(chǎng)景解析

    Java 緩存框架 Caffeine 應(yīng)用場(chǎng)景解析

    文章介紹Caffeine作為高性能Java本地緩存框架,基于W-TinyLFU算法,支持異步加載、靈活過(guò)期策略、內(nèi)存安全機(jī)制及統(tǒng)計(jì)監(jiān)控,重點(diǎn)解析其核心組件、高級(jí)特性與使用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • Java設(shè)計(jì)模式之工廠模式

    Java設(shè)計(jì)模式之工廠模式

    這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之工廠模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 詳解spring boot配置單點(diǎn)登錄

    詳解spring boot配置單點(diǎn)登錄

    本篇文章主要介紹了詳解spring boot配置單點(diǎn)登錄,常用的安全框架有spring security和apache shiro。shiro的配置和使用相對(duì)簡(jiǎn)單,本文使用shrio對(duì)接CAS服務(wù)。
    2017-03-03
  • JAVA基本概念詳解

    JAVA基本概念詳解

    本文主要介紹了Java的基本概念。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧,希望能夠給你帶來(lái)幫助
    2021-11-11
  • IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)登錄與注冊(cè)功能

    IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)登錄與注冊(cè)功能

    這篇文章主要介紹了IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項(xiàng)目實(shí)現(xiàn)動(dòng)態(tài)登錄與注冊(cè)功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 深入理解spring的AOP機(jī)制原理

    深入理解spring的AOP機(jī)制原理

    本篇文章主要介紹了深入理解spring的AOP機(jī)制原理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • 詳解為什么阿里巴巴禁止使用BigDecimal的equals方法做等值比較

    詳解為什么阿里巴巴禁止使用BigDecimal的equals方法做等值比較

    這篇文章主要介紹了詳解為什么阿里巴巴禁止使用BigDecimal的equals方法做等值比較,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java數(shù)據(jù)結(jié)構(gòu)和算法之冒泡,選擇和插入排序算法

    Java數(shù)據(jù)結(jié)構(gòu)和算法之冒泡,選擇和插入排序算法

    這篇文章主要為大家介紹了Java冒泡,選擇和插入排序算法 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • SpringCloud Feign 服務(wù)調(diào)用的實(shí)現(xiàn)

    SpringCloud Feign 服務(wù)調(diào)用的實(shí)現(xiàn)

    Feign是一個(gè)聲明性web服務(wù)客戶(hù)端。本文記錄多個(gè)服務(wù)之間使用Feign調(diào)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • SpringBoot使用AOP記錄接口操作日志詳解

    SpringBoot使用AOP記錄接口操作日志詳解

    這篇文章主要為大家詳細(xì)介紹了SpringBoot使用AOP記錄接口操作日志,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評(píng)論

竹山县| 临泽县| 巴南区| 苗栗县| 怀宁县| 北京市| 白河县| 濮阳市| 密云县| 万荣县| 文昌市| 饶阳县| 湖北省| 青田县| 三穗县| 深圳市| 霍州市| 佳木斯市| 民县| 奈曼旗| 成都市| 和政县| 桓仁| 江达县| 孟州市| 墨脱县| 时尚| 临沂市| 城口县| 华阴市| 留坝县| 桦南县| 兴业县| 团风县| 夏津县| 南昌市| 孝义市| 玛多县| 白玉县| 吉水县| 鞍山市|