激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java動態代理(設計模式)代碼詳解

Java動態代理(設計模式)代碼詳解

2021-03-11 14:03Terence_Jing Java教程

這篇文章主要介紹了Java動態代理(設計模式)代碼詳解,具有一定借鑒價值,需要的朋友可以參考下

基礎:需要具備面向對象設計思想,多態的思想,反射的思想;

java動態代理機制的出現,使得java開發人員不用手工編寫代理類,只要簡單地指定一組接口及委托類對象,便能動態地獲得代理類。代理類會負責將所有的方法調用分派到委托對象上反射執行,在分派執行的過程中,開發人員還可以按需調整委托類對象及其功能,這是一套非常靈活有彈性的代理框架。通過閱讀本文,讀者將會對java動態代理機制有更加深入的理解。本文首先從java動態代理的運行機制和特點出發,對其代碼進行了分析,推演了動態生成類的內部實現。

代理模式的基本概念和分類

代理模式:為其他對象提供一個代理,來控制對這個對象的訪問。代理對象起到中介作用,可以去掉服務或者增加額外的服務,或者引用別人的話:“代理類負責為委托類預處理消息,過濾消息并轉發消息,以及進行消息被委托類執行后的后續處理。”

代理模式在開發中的應用場景

遠程代理:為不同地理的對象提供局域網代表對象。

虛擬代理:根據需要將資源消耗很大的對象進行延遲,真正需要的時候進行創建。比如網頁中的先顯示文字再顯示圖片。

保護代理:控制不同用戶的訪問權限。比如:只有當客戶注冊成功之后,才可以進行增刪改查等操作。

智能引用代理:提供對目標代理額外的服務。

代理模式的實現方式

使用繼承和聚合實現動態代理,哪種更好呢!

?
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
public interface moveable {
    public void move();
}
public class car implements moveable{
    @override
      public void move() {
        try {
            thread.sleep(new random().nextint(1000));
            system.out.println("……行駛中……");
        }
        catch(interruptedexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }
}
public class car2 extends car{
    @override
      public void move()
      {
        //分離代碼,增加業務邏輯
        long starttime=system.currenttimemillis();
        system.out.println("汽車開始行駛……");
        super.move();
        long endtime=system.currenttimemillis();
        system.out.println("汽車結束行駛……時間:"+(endtime-starttime)+"ms");
    }
}

繼承方式實現代理

moveablecar2=newcar2();
car2.move();

聚合方式實現代理

carcar=newcar();
moveablem=newcar3(car);
m.move();

總結

使用繼承方式不夠靈活,當功能疊加的時候,只能臃腫的擴展代理類;
使用聚合的方式,代理之間可以相互傳遞,靈活的組合代理;

?
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
33
34
35
36
37
38
public class carlogproxy extends car{
    @override
      public void move()
      {
        //分離代碼,增加業務邏輯
        long starttime=system.currenttimemillis();
        system.out.println("日志開始……");
        super.move();
        long endtime=system.currenttimemillis();
        system.out.println("日志結束……");
    }
}
public class cartimeproxy implements moveable {
    public cartimeproxy(car car)
      {
        super();
        this.car=car;
    }
    private carcar;
    @override
      public void move() {
        //分離代碼,增加業務邏輯
        long starttime=system.currenttimemillis();
        system.out.println("汽車開始行駛……");
        car.move();
        long endtime=system.currenttimemillis();
        system.out.println("汽車結束行駛……時間:"+(endtime-starttime)+"ms");
    }
}
@test:
car car =new car();
cartimeproxy ctp=new cartimeproxy(car);
carlogproxy clp=new carlogproxy(ctp);
clp.move();
//還可以通過接口相互傳遞代理實例
carlogproxy clp1=new carlogproxy(car);
cartimeproxy ctp1=new cartimeproxy(clp1);
ctp1.move();

jdk動態代理和cglib動態代理

jdk動態代理

代理實現

如果不同的對象要實現相同功能的代理類,應該如何處置?

此時可以試著將其集成在同一個代理類中-----動態代理:實現對不同類/不同方法的代理;

大致過程如下:

Java動態代理(設計模式)代碼詳解

java動態代理類位于java.lang.reflect包下,一般主要涉及到一下兩個類:

(1)interfaceinvocationhandler:該接口中僅定義了一個方法publicobjectinvoke(objectobj,methodmethod,object[]args)

obj:一般是指代理類

method:是被代理的方法

args為該方法的參數數組。

這個抽象的方法在代理類中動態實現。

(2)proxy:該類即為動態代理類

statixobjectnewproxyinstance(classloaderloader,class[]interfaces,invocationhandlerh)

返回甙類類的一個實例,返回后的代理類可以當做被代理類使用(可以使用被代理類在接口中聲明過的方法);

實現實例:

?
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
@ timehandler
public class timehandler   implements invocationhandler {
    public timehandler(object target) {
        super();
        this.target = target;
    }
    private objecttarget;
    /*
  * 參數:
  * proxy 被代理對象
  * method 被代理對象的方法
  * args 方法的參數
  *
  * 返回值:
  * object 方法返回值
  */
    @override
      public object invoke(object proxy, method method,object[] args)
        throws throwable {
        long starttime=system.currenttimemillis();
        system.out.println("汽車開始行駛……");
        method.invoke(target);
        long endtime=system.currenttimemillis();
        system.out.println("汽車結束行駛……時間:"+(endtime-starttime)+"ms");
        return null;
    }
}
?
1
2
3
4
5
@被代理類的接口
public interface moveable {
  public void move();
}
@被代理的類
?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class car implements moveable{
    @override
      public void move() {
        try {
            thread.sleep(new random().nextint(1000));
            system.out.println("……行駛中……");
        }
        catch (interruptedexception e) {
            // todo auto-generated catch block
            e.printstacktrace();
        }
    }
}

@測試

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class test {
  /**
  * jdk動態代理的測試類
  */
  public static void main(string[] args) {
   car car=new car();
   invocationhandler h=new timehandler(car);
   class<?>cls=car.getclass();
   /*
    * loader 類加載器
    * interfaces 實現接口
    * h invocationhandler
    */
   moveable m=(moveable)proxy.newproxyinstance(cls.getclassloader(),cls.getinterfaces(),h);
   m.move();
  }
}

&&測試結果

Java動態代理(設計模式)代碼詳解

梳理總結

所為的dynamicproxy是這樣一種class:

它是在運行時生成的class,該class需要實現一組interface,使用動態代理類的時候,必須實現invocationhandler接口。

jdk動態代理的一般步驟

1.創建一個實現接口invocationhandler的類,它必須實現invoke()

2.創建被代理的類以及接口

3.調用proxy的靜態方法,創建一個代理類

newproxyinstance(classloaderloader,class[]interfaces,invocationhandlerh)

4.通過代理調用方法

Java動態代理(設計模式)代碼詳解

cglib動態代理的實現

代理實現

@引入cglib-node-2.2.jar包

@cglibproxy攔截類實現接口methodinterceptor:重寫intercept攔截方法

?
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
public class cglibproxy implements methodinterceptor {
    private enhancerenhancer=new enhancer();
    public object getproxy(class cl)
      {
        //設置創建子類的類
        enhancer.setsuperclass(cl);
        enhancer.setcallback(this);
        return enhancer.create();
    }
    /*
  * 攔截所有目標類方法的調用
  * object 目標類的實例
  * m 目標方法的反射對象
  * args 方法的參數
  * proxy 代理類的實例
  *
  */
    @override
      public object intercept(object obj, method m,object[] args,  methodproxy proxy)throws throwable
    {
        system.out.println("日志開始……");
        //代理類調用父類的方法
        proxy.invokesuper(obj, args);
        system.out.println("日志結束……");
        return null;
    }
}

@被代理類train

?
1
2
3
4
5
6
public class train {
  public void move()
  {
   system.out.println("火車行駛中……");
  }
}

@測試類

?
1
2
3
4
5
6
7
8
9
10
public class test {
  /**
  * cglibproxy動態代理測試類
  */
  public static void main(string[] args) {
   cglibproxy proxy=new cglibproxy();
   train t=(train)proxy.getproxy(train.class);
   t.move();
  }
}

##測試結果:

Java動態代理(設計模式)代碼詳解

梳理總結

使用cglibproxy實現動態代理的一般步驟

1、創建類實現接口methodinterceptor,并重寫intercept方法

2、創建被代理類

3、調用代理類自定義的方法,得到一個代理實例

4、通過代理實例調用被代理類的需要執行的方法

比較總結

jdk動態代理

1、只能代理實現了接口的類

2、沒有實現接口的類不能實現jdk的動態代理

cglib動態代理

1、針對類來實現代理

2、對執行目標類產生一個子類,通過方法攔截技術攔截所有父類方法的調用。

模擬代理產生步驟

思路:

實現功能:通過proxy的newproxyinstance返回代理對象

1、聲明一段源碼(動態產生代理)

2、編譯源碼(jdkcompilerapi)產生新的類(代理類)

3、將這個類load到內存當中,產生一個新的對象(代理對象)

4、返回代理對象

完善動態代理實現

首先得到系統編譯器,通過編譯器得到文件管理者,然后獲取文件,然后編譯器執行編譯任務,完成編譯之后,將class文件加載到類加載器中,通過構造方法得到實例,然后調用newinstance()接收一個對象的實例。

(1)拿到編譯器javacompilercompiler=toolprovider.getsystemjavacompiler();

(2)文件管理者standardjavafilemanagerfilemgr=compiler.getstandardfilemanager(null,null,null);

(3)獲取文件iterableunits=filemgr.getjavafileobjects(filename);

(4)編譯任務compilationtaskt=compiler.gettask(null,filemgr,null,null,null,units);

(5)load到內存

classloadercl=classloader.getsystemclassloader();

classc=cl.loadclass(”com.imooc.proxy.$proxy0”);

(6)通過代理對象的構造器構造實例

constructorctr=c.getconstructor(infce);

ctr.newinstance(newcar());

-------

上說所說,內部的業務邏輯是硬編碼的,如何實現真正的動態代理,動態的指定業務邏輯呢?

1、需要創建一個事務處理器,首先創建一個接口也就是invocationhandler,為了模擬jdk,這里把接口的名字和jdk事務處理器名稱一樣,同樣寫一個方法叫做invoke(),用來表示對某個對象的某個方法進行業務處理,所以需要把某個對象以及對象的方法作為invoke()方法的參數傳遞進來,invoke(objectobj,methodmethod),方法作為參數使用到了java反射,需要把此包引入。這樣invocationhandler接口就完成了。

2、創建事務處理實現類比如說時間代理timerproxy,實現了invocationhandler接口,這樣結構就成了

?
1
2
3
4
5
6
7
8
——————timerproxyimplementsinvocationhandler{
————————-@override
————————-voidinvoke(objectobj,methodmethod){
———————————//業務邏輯<br>
—————————————method.invoke(目標對象,參數);
————————————//業務邏輯<br>
——————————}
—————————}

需要將目標對象傳入,沒有參數可以不寫參數,創建代理對象的構造方法,初始化目標對象

3、在proxy類的newproxyinstance()方法中,除了要把目標class接口作為參數外,還需要把事務處理器invocationhandler傳進去,然后更改創建實例對象中硬編碼的部分用事務處理器方法替代即可。難點在于字符串的拼接。

總結

在我們項目中代理模式有自己的實際意義,比如說我們想要調用某個jar包下的某個類,可以在調用這個類之前之后添加一些特殊的業務邏輯,這種方式也叫作aop面向切面編程。(在不改變原有功能的基礎上,添加額外的功能。)

以上就是本文關于java動態代理(設計模式)代碼詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://blog.csdn.net/csdn_terence/article/details/52860221

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 伊久在线 | 一区二区三区欧美在线观看 | 毛片在线视频在线播放 | 日本在线视频免费 | 国产在线精品一区二区三区 | sm高h视频 | 禁漫天堂久久久久久久久久 | 成人毛片视频在线播放 | 一级网站 | 免费黄色小网站 | 99久久久精品 | 羞羞视频免费观看入口 | 色999国产 | 91社区电影 | 精品久久中文字幕 | 被摁着灌浓精囚禁高h1v1 | av亚洲在线观看 | 97porn| 国产精品久久久久久久久久久久久久久 | 一分钟免费观看完整版电影 | 视频一区国产 | 91精品国产一区二区三区四区在线 | 久综合色 | 久久久久久久久淑女av国产精品 | 久久精品男人 | 日韩av日韩 | 黄色大片网| 免费在线观看国产精品 | 娇喘在线 | 一级性色| 免费黄色a | 在线观看免费污视频 | 国内精品久久久久久久影视红豆 | 一级做a爱片久久毛片a高清 | 成人三级免费电影 | 草人人 | xxxxxx免费| 日韩精品久久久久久久电影99爱 | 性欧美视频在线观看 | 久久久久国产一区二区三区不卡 | 日韩精品一二区 |