国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Java的三種代理模式簡(jiǎn)述

Java的三種代理模式簡(jiǎn)述

2021-12-23 13:23閃客sun Java教程

這篇文章主要簡(jiǎn)述Java的三種代理模式,java的代理模式主要包括靜態(tài)代理、動(dòng)態(tài)代理、Cglib代理,感興趣的小伙伴可以參考下面文章的具體內(nèi)容

一、代理模式是什么

代理模式是一種設(shè)計(jì)模式,簡(jiǎn)單說(shuō)即是在不改變?cè)创a的情況下,實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象的功能擴(kuò)展。

比如有個(gè)歌手對(duì)象叫Singer,這個(gè)對(duì)象有一個(gè)唱歌方法叫sing()。

?
1
2
3
4
5
1 public class Singer{
2     public void sing(){
3         System.out.println("唱一首歌");
4    
5 }

假如你希望,通過(guò)你的某種方式生產(chǎn)出來(lái)的歌手對(duì)象,在唱歌前后還要想觀眾問(wèn)好和答謝,也即對(duì)目標(biāo)對(duì)象Singer的sing方法進(jìn)行功能擴(kuò)展

?
1
2
3
4
5
1 public void sing(){
2     System.out.println("向觀眾問(wèn)好");
3     System.out.println("唱一首歌");
4     System.out.println("謝謝大家");
5

但是往往你又不能直接對(duì)源代碼進(jìn)行修改,可能是你希望原來(lái)的對(duì)象還保持原來(lái)的樣子,又或許你提供的只是一個(gè)可插拔的插件,甚至你有可能都不知道你要對(duì)哪個(gè)目標(biāo)對(duì)象進(jìn)行擴(kuò)展。這時(shí)就需要用到j(luò)ava的代理模式了。網(wǎng)上好多用生活中的經(jīng)理人的例子來(lái)解釋“代理”,看似通俗易懂,但我覺(jué)得不適合程序員去理解。程序員應(yīng)該從代碼的本質(zhì)入手。

二、Java的三種代理模式

想要實(shí)現(xiàn)以上的需求有三種方式,這一部分我們只看三種模式的代碼怎么寫(xiě),先不涉及實(shí)現(xiàn)原理的部分。

1.靜態(tài)代理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1 public interface ISinger {
 2     void sing();
 3 }
 4
 5 /**
 6  *  目標(biāo)對(duì)象實(shí)現(xiàn)了某一接口
 7  */
 8 public class Singer implements ISinger{
 9     public void sing(){
10         System.out.println("唱一首歌");
11    
12 }
13
14 /**
15  *  代理對(duì)象和目標(biāo)對(duì)象實(shí)現(xiàn)相同的接口
16  */
17 public class SingerProxy implements ISinger{
18     // 接收目標(biāo)對(duì)象,以便調(diào)用sing方法
19     private ISinger target;
20     public UserDaoProxy(ISinger target){
21         this.target=target;
22     }
23     // 對(duì)目標(biāo)對(duì)象的sing方法進(jìn)行功能擴(kuò)展
24     public void sing() {
25         System.out.println("向觀眾問(wèn)好");
26         target.sing();
27         System.out.println("謝謝大家");
28     }
29 }

測(cè)試

?
1
2
3
4
5
6
7
8
9
10
11
12
13
1 /**
 2  * 測(cè)試類
 3  */
 4 public class Test {
 5     public static void main(String[] args) {
 6         //目標(biāo)對(duì)象
 7         ISinger target = new Singer();
 8         //代理對(duì)象
 9         ISinger proxy = new SingerProxy(target);
10         //執(zhí)行的是代理的方法
11         proxy.sing();
12     }
13 }

  總結(jié):其實(shí)這里做的事情無(wú)非就是,創(chuàng)建一個(gè)代理類SingerProxy,繼承了ISinger接口并實(shí)現(xiàn)了其中的方法。只不過(guò)這種實(shí)現(xiàn)特意包含了目標(biāo)對(duì)象的方法,正是這種特征使得看起來(lái)像是“擴(kuò)展”了目標(biāo)對(duì)象的方法。假使代理對(duì)象中只是簡(jiǎn)單地對(duì)sing方法做了另一種實(shí)現(xiàn)而沒(méi)有包含目標(biāo)對(duì)象的方法,也就不能算作代理模式了。所以這里的包含是關(guān)鍵。

  缺點(diǎn):這種實(shí)現(xiàn)方式很直觀也很簡(jiǎn)單,但其缺點(diǎn)是代理對(duì)象必須提前寫(xiě)出,如果接口層發(fā)生了變化,代理對(duì)象的代碼也要進(jìn)行維護(hù)。如果能在運(yùn)行時(shí)動(dòng)態(tài)地寫(xiě)出代理對(duì)象,不但減少了一大批代理類的代碼,也少了不斷維護(hù)的煩惱,不過(guò)運(yùn)行時(shí)的效率必定受到影響。這種方式就是接下來(lái)的動(dòng)態(tài)代理。

2.動(dòng)態(tài)代理(也叫JDK代理)

跟靜態(tài)代理的前提一樣,依然是對(duì)Singer對(duì)象進(jìn)行擴(kuò)展

?
1
2
3
4
5
6
7
8
9
10
11
12
1 public interface ISinger {
 2     void sing();
 3 }
 4
 5 /**
 6  *  目標(biāo)對(duì)象實(shí)現(xiàn)了某一接口
 7  */
 8 public class Singer implements ISinger{
 9     public void sing(){
10         System.out.println("唱一首歌");
11    
12 }

這回直接上測(cè)試,由于java底層封裝了實(shí)現(xiàn)細(xì)節(jié)(之后會(huì)詳細(xì)講),所以代碼非常簡(jiǎn)單,格式也基本上固定。

調(diào)用Proxy類的靜態(tài)方法newProxyInstance即可,該方法會(huì)返回代理類對(duì)象

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
接收的三個(gè)參數(shù)依次為:

  • ClassLoader loader:指定當(dāng)前目標(biāo)對(duì)象使用類加載器,寫(xiě)法固定
  • Class<?>[] interfaces:目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類型,寫(xiě)法固定
  • InvocationHandler h:事件處理接口,需傳入一個(gè)實(shí)現(xiàn)類,一般直接使用匿名內(nèi)部類

測(cè)試代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1 public class Test{
 2     public static void main(String[] args) {
 3   Singer target = new Singer();
 4         ISinger proxy  = (ISinger) Proxy.newProxyInstance(
 5                 target.getClass().getClassLoader(),
 6                 target.getClass().getInterfaces(),
 7                 new InvocationHandler() {
 8                     @Override
 9                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
10                         System.out.println("向觀眾問(wèn)好");
11                         //執(zhí)行目標(biāo)對(duì)象方法
12                         Object returnValue = method.invoke(target, args);
13                         System.out.println("謝謝大家");
14                         return returnValue;
15                     }
16                 });
17         proxy.sing();
18     }
19 }

總結(jié):以上代碼只有標(biāo)黃的部分是需要自己寫(xiě)出,其余部分全都是固定代碼。由于java封裝了newProxyInstance這個(gè)方法的實(shí)現(xiàn)細(xì)節(jié),所以使用起來(lái)才能這么方便,具體的底層原理將會(huì)在下一小節(jié)說(shuō)明。

缺點(diǎn):可以看出靜態(tài)代理和JDK代理有一個(gè)共同的缺點(diǎn),就是目標(biāo)對(duì)象必須實(shí)現(xiàn)一個(gè)或多個(gè)接口,加入沒(méi)有,則可以使用Cglib代理。

3.Cglib代理

前提條件:

  • 需要引入cglib的jar文件,由于Spring的核心包中已經(jīng)包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar
  • 目標(biāo)類不能為final
  • 目標(biāo)對(duì)象的方法如果為final/static,那么就不會(huì)被攔截,即不會(huì)執(zhí)行目標(biāo)對(duì)象額外的業(yè)務(wù)方法
?
1
2
3
4
5
6
7
8
9
1 /**
2  * 目標(biāo)對(duì)象,沒(méi)有實(shí)現(xiàn)任何接口
3  */
4 public class Singer{
5
6     public void sing() {
7         System.out.println("唱一首歌");
8     }
9 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1 /**
 2  * Cglib子類代理工廠
 3  */
 4 public class ProxyFactory implements MethodInterceptor{
 5     // 維護(hù)目標(biāo)對(duì)象
 6     private Object target;
 7
 8     public ProxyFactory(Object target) {
 9         this.target = target;
10     }
11
12     // 給目標(biāo)對(duì)象創(chuàng)建一個(gè)代理對(duì)象
13     public Object getProxyInstance(){
14         //1.工具類
15         Enhancer en = new Enhancer();
16         //2.設(shè)置父類
17         en.setSuperclass(target.getClass());
18         //3.設(shè)置回調(diào)函數(shù)
19         en.setCallback(this);
20         //4.創(chuàng)建子類(代理對(duì)象)
21         return en.create();
22     }
23
24     @Override
25     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
26         System.out.println("向觀眾問(wèn)好");
27         //執(zhí)行目標(biāo)對(duì)象的方法
28         Object returnValue = method.invoke(target, args);
29         System.out.println("謝謝大家");
30         return returnValue;
31     }
32 }

這里的代碼也非常固定,只有標(biāo)黃部分是需要自己寫(xiě)出

測(cè)試

?
1
2
3
4
5
6
7
8
9
10
11
12
13
1 /**
 2  * 測(cè)試類
 3  */
 4 public class Test{
 5     public static void main(String[] args){
 6         //目標(biāo)對(duì)象
 7         Singer target = new Singer();
 8         //代理對(duì)象
 9         Singer proxy = (Singer)new ProxyFactory(target).getProxyInstance();
10         //執(zhí)行代理對(duì)象的方法
11         proxy.sing();
12     }
13 }

總結(jié):三種代理模式各有優(yōu)缺點(diǎn)和相應(yīng)的適用范圍,主要看目標(biāo)對(duì)象是否實(shí)現(xiàn)了接口。以Spring框架所選擇的代理模式舉例

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

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

原文鏈接:https://www.cnblogs.com/flashsun/p/7286475.html

延伸 · 閱讀

精彩推薦
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線程模擬多人同時(shí)搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程20個(gè)非常實(shí)用的Java程序代碼片段

    20個(gè)非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個(gè)非常實(shí)用的Java程序片段,對(duì)java開(kāi)發(fā)項(xiàng)目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒(méi)有升過(guò)級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml與Java對(duì)象的轉(zhuǎn)換詳解

    xml與Java對(duì)象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對(duì)象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望...

    spcoder14552021-10-18
主站蜘蛛池模板: 红杏首页 | 日韩精品视频一区二区三区 | 欧美一区二区三区在线 | 久久久一 | 亚洲激情一区二区 | 狠狠天天| 久久伊人官网 | 黄片毛片免费观看 | 玖玖精品在线 | 国产精品一区二区三区四区五区 | 在线观看av网站永久 | 精品久久久久久久 | 精品成人免费一区二区在线播放 | 亚洲视频在线观看 | 91精品国产综合久久香蕉 | 中文字幕av一区二区 | 久久久久久成人 | 日本在线观看一区 | 成人福利 | 成人综合网站 | 视色影院 | 免费的污网站 | 综合久久综合久久 | 99久久99| 欧美日韩一区在线观看 | 欧美精品在线一区二区三区 | 中文字幕在线一区 | 久久视频一区 | 欧美在线免费观看 | 日韩午夜影院 | 在线精品国产一区二区三区 | 一区二区三区视频在线观看 | 婷婷色av | 日本中文字幕在线观看 | 亚洲视频中文字幕 | 黄色国产片 | 99精品国产高清在线观看 | 日韩精品专区 | 色婷婷狠狠 | 一区免费看 | 黄色二区 |