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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

JDK动态代理实现简单AOP--转

發(fā)布時(shí)間:2025/4/5 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JDK动态代理实现简单AOP--转 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JDK?動(dòng)態(tài)代理是?java?反射的一個(gè)重要特性。它在某種方面為?java?提供了動(dòng)態(tài)性的特性,給應(yīng)用帶來(lái)了無(wú)限的空間。大名鼎鼎的?Hessian?、?Spring AOP?基于動(dòng)態(tài)代理實(shí)現(xiàn)。本文將簡(jiǎn)單的介紹?JDK?動(dòng)態(tài)代理使用。

?

關(guān)于代理模式

?

代理模式是非常常用的一種設(shè)計(jì)模式,在我們的應(yīng)用中經(jīng)常被使用。一般場(chǎng)景是,我們有一個(gè)現(xiàn)成的類,它的功能比較的完善了,但是還是存在某些欠缺,這個(gè)時(shí)候我們需要去擴(kuò)展一些新的功能,但又不想去重造輪子,這個(gè)時(shí)候可以使用代理類來(lái)替代原來(lái)的目標(biāo)類,通過(guò)組合的模式,增加一種為目標(biāo)類增加一些額外的功能。

代理模式的類結(jié)構(gòu)圖一般如下:

?

圖1:代理模式類結(jié)構(gòu)圖

圖2:代理模式序列圖

?

JDK?動(dòng)態(tài)代理

?

所謂?JDK?動(dòng)態(tài)代理就是在運(yùn)行時(shí)動(dòng)態(tài)生成紅色的代理類的過(guò)程。和靜態(tài)代理不一樣的地方是靜態(tài)代理在編譯期就要完成代理類?的實(shí)現(xiàn)。那么動(dòng)態(tài)代理是如何實(shí)現(xiàn)的呢?

根據(jù)下面的例子,一步一步來(lái)看。

假設(shè)有這樣一個(gè)接口?Speak:

  • package?proxy;??
  • public?interface?Speak?{??
  • ????public?void?sayHello();??
  • }??
  • ?

    ?

    實(shí)現(xiàn)類?PeopleSpeak.

    ?

  • package?proxy;??
  • public?class?PersonSpeak?implements?Speak?{??
  • ????public?void?sayHello()?{??
  • ????????System.out.println("hello");??
  • ????}??
  • }??
  • ?

    ?

    當(dāng)我們?nèi)フ{(diào)用?PersonSpeak?的?sayHello?的時(shí)候,很顯然是輸出?hello?。現(xiàn)在我們需要通過(guò)動(dòng)態(tài)代理在運(yùn)行時(shí)動(dòng)態(tài)的生成Speak?的代理類,并在調(diào)用?sayHello?方法的前后做一些輸出。完成類似?aop?的功能。

    根據(jù)以上的思路,我們需要有一個(gè)?PersonSpeak?的代理類,它持了?PersonSpeak?的對(duì)象,這樣就能很方便的完成這個(gè)任務(wù)。如果用靜態(tài)代理實(shí)現(xiàn)顯然是很簡(jiǎn)單,那么用動(dòng)態(tài)代理如何實(shí)現(xiàn)呢?

    這個(gè)時(shí)候我們可以使用?java?反射里的?Proxy?類。此類是?JDK?動(dòng)態(tài)代理的核心類。?Proxy?類擁有一個(gè)在運(yùn)行期動(dòng)態(tài)創(chuàng)建類的功能。動(dòng)態(tài)的去創(chuàng)建一個(gè)?Speak?的子類,同時(shí)該子類持有?PersonSpeak?類的一個(gè)實(shí)例,該子類的功能就是實(shí)現(xiàn)上述第一部分代理類的功能。

    關(guān)于?java?反射的?Method?、?Field?、?Class?、?Construtor?等這里不做介紹,重點(diǎn)介紹?Proxy和?InvocationHandler?類。

    Proxy和InvocationHandler?類簡(jiǎn)介

    Proxy?類提供了非常重要的方法,該方法能夠動(dòng)態(tài)的生成幾個(gè)接口的實(shí)現(xiàn)類。具體的實(shí)現(xiàn)過(guò)程由?ProxyGenerator?類來(lái)實(shí)現(xiàn),這是比較低層的一個(gè)類,這里不做過(guò)多描述。同時(shí)該動(dòng)態(tài)類需要持有一個(gè)實(shí)現(xiàn)了?InvocationHandler?接口的子類對(duì)象。InvocationHandler?接口的子類對(duì)象是我們目標(biāo)類的又一層代理。對(duì)于接口里面的每個(gè)方法實(shí)現(xiàn),都是通過(guò)調(diào)用InvocationHandler?接口的子類對(duì)象的反射調(diào)用。也就是說(shuō)動(dòng)態(tài)代理類實(shí)際上是?InvocationHandler?子類對(duì)象的一個(gè)代理。那么?InvocationHandler?子類對(duì)象有時(shí)我們目標(biāo)類的代理。通過(guò)這樣層層代理我們就能實(shí)現(xiàn)上述的功能了。這句話可能不是很好理解,但是確實(shí)就是這么實(shí)現(xiàn)的,也許通過(guò)下面的圖就能更好的理解:

    ?

    圖3:JDK動(dòng)態(tài)代理調(diào)用過(guò)程

    ?

    可以從上圖看出來(lái),?JDK?動(dòng)態(tài)反射并不是那么簡(jiǎn)單的一層代理,而是通過(guò)層層代理,最終通過(guò)?Method?的反射來(lái)調(diào)用目標(biāo)對(duì)象的方法,而?aop?的實(shí)現(xiàn)可以放在?InvocationHandler?的是實(shí)現(xiàn)類里。

    那么根據(jù)上述關(guān)于動(dòng)態(tài)代理的簡(jiǎn)介,要實(shí)現(xiàn)?PersonSpeak?的?aop?,需要做兩件事情

  • 1.???????實(shí)現(xiàn)一個(gè)持有?Speak?對(duì)象的?InvocationHandler?子類,改子類通過(guò)?Mechod?反射調(diào)用?PersonSpeak?的方法,并在調(diào)用方法前后實(shí)現(xiàn)?aop?功能。
  • 2.???????實(shí)現(xiàn)一個(gè)能動(dòng)態(tài)創(chuàng)建?Speak?子類的代理類工廠,改工廠能動(dòng)態(tài)的創(chuàng)建?Speak?子類。
  • ?

    具體實(shí)現(xiàn)如下:

  • SpeakInvocationHandler (?實(shí)現(xiàn)?InvocationHandler?接口?)
  • 可以看出該類的?invoke?方法實(shí)現(xiàn)?aop?的關(guān)鍵,所有方法都是通過(guò)?invoke?來(lái)調(diào)用,?invoke?內(nèi)部通過(guò)反射來(lái)調(diào)用目標(biāo)對(duì)象?target?,同時(shí)在調(diào)用前后實(shí)現(xiàn)了?aop?。

  • package?proxy;??
  • import?java.lang.reflect.InvocationHandler;??
  • import?java.lang.reflect.Method;??
  • public?class?SpeakInvocationHandler?implements?InvocationHandler?{??
  • ????public?Object?target;??
  • ????SpeakInvocationHandler(Object?target)?{??
  • ????????this.target?=?target;??
  • ????}??
  • ????public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{??
  • ????????System.out.println(method.getName()?+?"?invoked!");??
  • ????????Object?result?=?method.invoke(target,?args);??
  • ????????System.out.println(method.getName()?+?"?return!");??
  • ????????return?result;??
  • ????}??
  • }??
  • ?

  • ProxyFactory
  • ?

  • package?proxy;??
  • import?java.lang.reflect.InvocationHandler;??
  • import?java.lang.reflect.Proxy;??
  • public?class?ProxyFactory?{??
  • ????Class?????????????cls;??
  • ????InvocationHandler?h;??
  • ????public?ProxyFactory(String?className,?InvocationHandler?h)?{??
  • ????????try?{??
  • ????????????cls?=?Class.forName(className);??
  • ????????????this.h?=?h;??
  • ????????}?catch?(ClassNotFoundException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • ????public?Object?createProxyObject()?{??
  • ????????return?Proxy.newProxyInstance(cls.getClassLoader(),?cls.getInterfaces(),?h);??
  • ????}??
  • }??
  • ?

    ProxyFactory?主要是通過(guò)反射的?Proxy?類動(dòng)態(tài)的去創(chuàng)建接口的子類,同時(shí)該子類是?InvocationHandler?的一個(gè)代理,所有的方法實(shí)現(xiàn),都是通過(guò)?InvocationHandler?代理來(lái)調(diào)用。

    ?

    最后來(lái)看下?Main?函數(shù):

    ?

    ?

  • package?proxy;??
  • import?java.lang.reflect.InvocationHandler;??
  • public?class?ProxyTest?{??
  • ????public?static?void?main(String?args[])?{??
  • ????????Speak?s?=?new?PersonSpeak();??
  • ????????InvocationHandler?h?=?new?SpeakInvocationHandler(s);??
  • ????????ProxyFactory?proxyFactory?=?new?ProxyFactory(PersonSpeak.class.getName(),?h);??
  • ????????Speak?speakProxy?=?(Speak)?proxyFactory.createProxyObject();??
  • ????????speakProxy.sayHello();??
  • ????}??
  • }??
  • ?

    ?

    得到的輸出結(jié)果如下:

    ??sayHello invoked!

    hello

    sayHello return!

    ?

    ?

    從輸出結(jié)果可以看出紅色的輸出部分正是我們通過(guò)動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)的。通過(guò)如上的過(guò)程完成了正果動(dòng)態(tài)代理的過(guò)程。

    除了實(shí)現(xiàn)?AOP?,動(dòng)態(tài)代理還可以用于實(shí)現(xiàn)遠(yuǎn)程服務(wù)代理。比如說(shuō)?Hessian?就是通過(guò)動(dòng)態(tài)創(chuàng)建遠(yuǎn)程服務(wù)代理類來(lái)調(diào)用遠(yuǎn)程服務(wù),從而使應(yīng)用對(duì)遠(yuǎn)程服務(wù)透明化。?Hessian?調(diào)用過(guò)程如下:

    ?

    圖4:Hessian遠(yuǎn)程服務(wù)調(diào)用過(guò)程

    ?

    總結(jié)

    ?

    JDK?動(dòng)態(tài)代理是?java?反射的一個(gè)非常重要的特性,?JDK?動(dòng)態(tài)代理類還可以用來(lái)作為?SOAP?的遠(yuǎn)程服務(wù)代理類,總之它在某種程度上提供了?java?的動(dòng)態(tài)性的特點(diǎn),為應(yīng)用提供了很大的靈活性。

    ?

    原文:http://blog.csdn.net/abing37/article/details/5449401

    轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/3942082.html

    總結(jié)

    以上是生活随笔為你收集整理的JDK动态代理实现简单AOP--转的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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