亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁 Java Java入門 java的三種代理模式分別是什么

java的三種代理模式分別是什么

Jan 30, 2021 am 09:44 AM
java 代理模式

java的三種代理模式分別是什么

首先來簡單說明一下什么是代理模式。

代理(Proxy)是一種設(shè)計模式,提供了對目標(biāo)對象另外的訪問方式;即通過代理對象訪問目標(biāo)對象.這樣做的好處是:可以在目標(biāo)對象實現(xiàn)的基礎(chǔ)上,增強額外的功能操作,即擴展目標(biāo)對象的功能.
這里使用到編程中的一個思想:不要隨意去修改別人已經(jīng)寫好的代碼或者方法,如果需改修改,可以通過代理的方式來擴展該方法

舉個例子來說明代理的作用:假設(shè)我們想邀請一位明星,那么并不是直接連接明星,而是聯(lián)系明星的經(jīng)紀(jì)人,來達(dá)到同樣的目的.明星就是一個目標(biāo)對象,他只要負(fù)責(zé)活動中的節(jié)目,而其他瑣碎的事情就交給他的代理人(經(jīng)紀(jì)人)來解決.這就是代理思想在現(xiàn)實中的一個例子

用圖表示如下:

001e1804cf6f3b05501e38cdabd20c0.png

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

1.1.靜態(tài)代理

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

下面舉個案例來解釋:
模擬保存動作,定義一個保存動作的接口:IUserDao.java,然后目標(biāo)對象實現(xiàn)這個接口的方法UserDao.java,此時如果使用靜態(tài)代理方式,就需要在代理對象(UserDaoProxy.java)中也實現(xiàn)IUserDao接口.調(diào)用的時候通過調(diào)用代理對象的方法來調(diào)用目標(biāo)對象.
需要注意的是,代理對象與目標(biāo)對象要實現(xiàn)相同的接口,然后通過調(diào)用相同的方法來調(diào)用目標(biāo)對象的方法

代碼示例:
接口:IUserDao.java

/**
 * 接口
 */public interface IUserDao {    void save();
}

目標(biāo)對象:UserDao.java

/**
 * 接口實現(xiàn)
 * 目標(biāo)對象
 */public class UserDao implements IUserDao {    public void save() {
        System.out.println("----已經(jīng)保存數(shù)據(jù)!----");
    }
}

代理對象:UserDaoProxy.java

/**
 * 代理對象,靜態(tài)代理
 */public class UserDaoProxy implements IUserDao{    //接收保存目標(biāo)對象
    private IUserDao target;    public UserDaoProxy(IUserDao target){        this.target=target;
    }    public void save() {
        System.out.println("開始事務(wù)...");
        target.save();//執(zhí)行目標(biāo)對象的方法
        System.out.println("提交事務(wù)...");
    }
}

(學(xué)習(xí)視頻分享:java視頻教程

測試類:App.java

/**
 * 測試類
 */public class App {    public static void main(String[] args) {        //目標(biāo)對象
        UserDao target = new UserDao();        //代理對象,把目標(biāo)對象傳給代理對象,建立代理關(guān)系
        UserDaoProxy proxy = new UserDaoProxy(target);

        proxy.save();//執(zhí)行的是代理的方法
    }
}

靜態(tài)代理總結(jié):
1.可以做到在不修改目標(biāo)對象的功能前提下,對目標(biāo)功能擴展.
2.缺點:

因為代理對象需要與目標(biāo)對象實現(xiàn)一樣的接口,所以會有很多代理類,類太多.同時,一旦接口增加方法,目標(biāo)對象與代理對象都要維護.

如何解決靜態(tài)代理中的缺點呢?答案是可以使用動態(tài)代理方式

1.2.動態(tài)代理

動態(tài)代理有以下特點:
1.代理對象,不需要實現(xiàn)接口
2.代理對象的生成,是利用JDK的API,動態(tài)的在內(nèi)存中構(gòu)建代理對象(需要我們指定創(chuàng)建代理對象/目標(biāo)對象實現(xiàn)的接口的類型)
3.動態(tài)代理也叫做:JDK代理,接口代理

JDK中生成代理對象的API
代理類所在包:java.lang.reflect.Proxy
JDK實現(xiàn)代理只需要使用newProxyInstance方法,但是該方法需要接收三個參數(shù),完整的寫法是:

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

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

ClassLoader loader,:指定當(dāng)前目標(biāo)對象使用類加載器,獲取加載器的方法是固定的

Class[] interfaces,:目標(biāo)對象實現(xiàn)的接口的類型,使用泛型方式確認(rèn)類型

InvocationHandler h:事件處理,執(zhí)行目標(biāo)對象的方法時,會觸發(fā)事件處理器的方法,會把當(dāng)前執(zhí)行目標(biāo)對象的方法作為參數(shù)傳入

代碼示例:
接口類IUserDao.java以及接口實現(xiàn)類,目標(biāo)對象UserDao是一樣的,沒有做修改.在這個基礎(chǔ)上,增加一個代理工廠類(ProxyFactory.java),將代理類寫在這個地方,然后在測試類(需要使用到代理的代碼)中先建立目標(biāo)對象和代理對象的聯(lián)系,然后代用代理對象的中同名方法

代理工廠類:ProxyFactory.java

/**
 * 創(chuàng)建動態(tài)代理對象
 * 動態(tài)代理不需要實現(xiàn)接口,但是需要指定接口類型
 */public class ProxyFactory{    //維護一個目標(biāo)對象
    private Object target;    public ProxyFactory(Object target){        this.target=target;
    }   //給目標(biāo)對象生成代理對象
    public Object getProxyInstance(){        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),                new InvocationHandler() {                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("開始事務(wù)2");                        //執(zhí)行目標(biāo)對象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事務(wù)2");                        return returnValue;
                    }
                }
        );
    }

}

測試類:App.java

/**
 * 測試類
 */public class App {    public static void main(String[] args) {        // 目標(biāo)對象
        IUserDao target = new UserDao();        // 【原始的類型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());        // 給目標(biāo)對象,創(chuàng)建代理對象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();        // class $Proxy0   內(nèi)存中動態(tài)生成的代理對象
        System.out.println(proxy.getClass());        // 執(zhí)行方法   【代理對象】
        proxy.save();
    }
}

總結(jié):
代理對象不需要實現(xiàn)接口,但是目標(biāo)對象一定要實現(xiàn)接口,否則不能用動態(tài)代理

1.3.Cglib代理

上面的靜態(tài)代理和動態(tài)代理模式都是要求目標(biāo)對象是實現(xiàn)一個接口的目標(biāo)對象,但是有時候目標(biāo)對象只是一個單獨的對象,并沒有實現(xiàn)任何的接口,這個時候就可以使用以目標(biāo)對象子類的方式類實現(xiàn)代理,這種方法就叫做:Cglib代理

Cglib代理,也叫作子類代理,它是在內(nèi)存中構(gòu)建一個子類對象從而實現(xiàn)對目標(biāo)對象功能的擴展.

JDK的動態(tài)代理有一個限制,就是使用動態(tài)代理的對象必須實現(xiàn)一個或多個接口,如果想代理沒有實現(xiàn)接口的類,就可以使用Cglib實現(xiàn).Cglib是一個強大的高性能的代碼生成包,它可以在運行期擴展java類與實現(xiàn)java接口.它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)Cglib包的底層是通過使用一個小而塊的字節(jié)碼處理框架ASM來轉(zhuǎn)換字節(jié)碼并生成新的類.不鼓勵直接使用ASM,因為它要求你必須對JVM內(nèi)部結(jié)構(gòu)包括class文件的格式和指令集都很熟悉.

Cglib子類代理實現(xiàn)方法:
1.需要引入cglib的jar文件,但是Spring的核心包中已經(jīng)包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2.引入功能包后,就可以在內(nèi)存中動態(tài)構(gòu)建子類
3.代理的類不能為final,否則報錯
4.目標(biāo)對象的方法如果為final/static,那么就不會被攔截,即不會執(zhí)行目標(biāo)對象額外的業(yè)務(wù)方法.

代碼示例:
目標(biāo)對象類:UserDao.java

/**
 * 目標(biāo)對象,沒有實現(xiàn)任何接口
 */public class UserDao {    public void save() {
        System.out.println("----已經(jīng)保存數(shù)據(jù)!----");
    }
}

Cglib代理工廠:ProxyFactory.java

/**
 * Cglib子類代理工廠
 * 對UserDao在內(nèi)存中動態(tài)構(gòu)建一個子類對象
 */public class ProxyFactory implements MethodInterceptor{    //維護目標(biāo)對象
    private Object target;    public ProxyFactory(Object target) {        this.target = target;
    }    //給目標(biāo)對象創(chuàng)建一個代理對象
    public Object getProxyInstance(){        //1.工具類
        Enhancer en = new Enhancer();        //2.設(shè)置父類
        en.setSuperclass(target.getClass());        //3.設(shè)置回調(diào)函數(shù)
        en.setCallback(this);        //4.創(chuàng)建子類(代理對象)
        return en.create();

    }    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("開始事務(wù)...");        //執(zhí)行目標(biāo)對象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事務(wù)...");        return returnValue;
    }
}

測試類:

/**
 * 測試類
 */public class App {    @Test
    public void test(){        //目標(biāo)對象
        UserDao target = new UserDao();        //代理對象
        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();        //執(zhí)行代理對象的方法
        proxy.save();
    }
}

在Spring的AOP編程中:
如果加入容器的目標(biāo)對象有實現(xiàn)接口,用JDK代理
如果目標(biāo)對象沒有實現(xiàn)接口,用Cglib代理

相關(guān)推薦:java入門教程

以上是java的三種代理模式分別是什么的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
VSCODE設(shè)置。JSON位置 VSCODE設(shè)置。JSON位置 Aug 01, 2025 am 06:12 AM

settings.json文件位于用戶級或工作區(qū)級路徑,用于自定義VSCode設(shè)置。1.用戶級路徑:Windows為C:\Users\\AppData\Roaming\Code\User\settings.json,macOS為/Users//Library/ApplicationSupport/Code/User/settings.json,Linux為/home//.config/Code/User/settings.json;2.工作區(qū)級路徑:項目根目錄下的.vscode/settings

如何使用JDBC處理Java的交易? 如何使用JDBC處理Java的交易? Aug 02, 2025 pm 12:29 PM

要正確處理JDBC事務(wù),必須先關(guān)閉自動提交模式,再執(zhí)行多個操作,最后根據(jù)結(jié)果提交或回滾;1.調(diào)用conn.setAutoCommit(false)以開始事務(wù);2.執(zhí)行多個SQL操作,如INSERT和UPDATE;3.若所有操作成功則調(diào)用conn.commit(),若發(fā)生異常則調(diào)用conn.rollback()確保數(shù)據(jù)一致性;同時應(yīng)使用try-with-resources管理資源,妥善處理異常并關(guān)閉連接,避免連接泄漏;此外建議使用連接池、設(shè)置保存點實現(xiàn)部分回滾,并保持事務(wù)盡可能短以提升性能。

在Java的掌握依賴注入春季和Guice 在Java的掌握依賴注入春季和Guice Aug 01, 2025 am 05:53 AM

依賴性(di)IsadesignpatternwhereObjectsReceivedenciesenciesExtern上,推廣looseSecouplingAndEaseerTestingThroughConstructor,setter,orfieldInjection.2.springfraMefringframeWorkSannotationsLikeLikeLike@component@component,@component,@service,@autowiredwithjava-service和@autowiredwithjava-ligatiredwithjava-lase-lightike

如何使用Java的日歷? 如何使用Java的日歷? Aug 02, 2025 am 02:38 AM

使用java.time包中的類替代舊的Date和Calendar類;2.通過LocalDate、LocalDateTime和LocalTime獲取當(dāng)前日期時間;3.使用of()方法創(chuàng)建特定日期時間;4.利用plus/minus方法不可變地增減時間;5.使用ZonedDateTime和ZoneId處理時區(qū);6.通過DateTimeFormatter格式化和解析日期字符串;7.必要時通過Instant與舊日期類型兼容;現(xiàn)代Java中日期處理應(yīng)優(yōu)先使用java.timeAPI,它提供了清晰、不可變且線

了解Java虛擬機(JVM)內(nèi)部 了解Java虛擬機(JVM)內(nèi)部 Aug 01, 2025 am 06:31 AM

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

Google Chrome無法打開本地文件 Google Chrome無法打開本地文件 Aug 01, 2025 am 05:24 AM

ChromecanopenlocalfileslikeHTMLandPDFsbyusing"Openfile"ordraggingthemintothebrowser;ensuretheaddressstartswithfile:///;2.SecurityrestrictionsblockAJAX,localStorage,andcross-folderaccessonfile://;usealocalserverlikepython-mhttp.server8000tor

比較Java框架:Spring Boot vs Quarkus vs Micronaut 比較Java框架:Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

前形式攝取,quarkusandmicronautleaddueTocile timeProcessingandGraalvSupport,withquarkusoftenpernperforminglightbetterine nosserless notelless centarios.2。

了解網(wǎng)絡(luò)端口和防火墻 了解網(wǎng)絡(luò)端口和防火墻 Aug 01, 2025 am 06:40 AM

NetworkPortSandFireWallsworkTogetHertoEnableCommunication whereSeringSecurity.1.NetWorkPortSareVirtualendPointSnumbered0-655 35,with-Well-with-Newonportslike80(HTTP),443(https),22(SSH)和25(smtp)sindiessingspefificservices.2.portsoperateervertcp(可靠,c

See all articles