在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>java源碼下載>

java的動(dòng)態(tài)代理機(jī)制和作用

大?。?/span>0.4 MB 人氣: 2017-09-27 需要積分:1
學(xué)習(xí)Spring的時(shí)候,我們知道Spring主要有兩大思想,一個(gè)是IoC,另一個(gè)就是AOP,對(duì)于IoC,依賴注入就不用多說(shuō)了,而對(duì)于Spring的核心AOP來(lái)說(shuō),我們不但要知道怎么通過(guò)AOP來(lái)滿足的我們的功能,我們更需要學(xué)習(xí)的是其底層是怎么樣的一個(gè)原理,而AOP的原理就是java的動(dòng)態(tài)代理機(jī)制,所以本篇隨筆就是對(duì)java的動(dòng)態(tài)機(jī)制進(jìn)行一個(gè)回顧。
  在java的動(dòng)態(tài)代理機(jī)制中,有兩個(gè)重要的類或接口,一個(gè)是 InvocationHandler(Interface)、另一個(gè)則是 Proxy(Class),這一個(gè)類和接口是實(shí)現(xiàn)我們動(dòng)態(tài)代理所必須用到的。首先我們先來(lái)看看java的API幫助文檔是怎么樣對(duì)這兩個(gè)類進(jìn)行描述的:
  InvocationHandler:
  InvocationHandler isthe interfaceimplemented bythe invocation handler ofa proxy instance. Eachproxy instance hasan associated invocation handler. When amethodisinvokedonaproxyinstance,themethodinvocationisencodedanddispatchedtotheinvokemethodofitsinvocationhandler.
  每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn)InvocationHandler這個(gè)接口,并且每個(gè)代理類的實(shí)例都關(guān)聯(lián)到了一個(gè)handler,當(dāng)我們通過(guò)代理對(duì)象調(diào)用一個(gè)方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)為由InvocationHandler這個(gè)接口的 invoke 方法來(lái)進(jìn)行調(diào)用。我們來(lái)看看InvocationHandler這個(gè)接口的唯一一個(gè)方法 invoke 方法:
  Object invoke(Object proxy, Methodmethod, Object[] args) throwsThrowable
  我們看到這個(gè)方法一共接受三個(gè)參數(shù),那么這三個(gè)參數(shù)分別代表什么呢?
  proxy:  指代我們所代理的那個(gè)真實(shí)對(duì)象
  method:  指代的是我們所要調(diào)用真實(shí)對(duì)象的某個(gè)方法的Method對(duì)象
  args:  指代的是調(diào)用真實(shí)對(duì)象某個(gè)方法時(shí)接受的參數(shù)
  如果不是很明白,等下通過(guò)一個(gè)實(shí)例會(huì)對(duì)這幾個(gè)參數(shù)進(jìn)行更深的講解。
  接下來(lái)我們來(lái)看看Proxy這個(gè)類:
  Proxy provides staticmethods forcreating dynamicproxy classes andinstances, andit isalso the superclass ofall dynamicproxy classes created bythose methods.
  Proxy這個(gè)類的作用就是用來(lái)動(dòng)態(tài)創(chuàng)建一個(gè)代理對(duì)象的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個(gè)方法:
  publicstaticObject newProxyInstance(ClassLoader loader, Class《?》[] interfaces, InvocationHandler h) throwsIllegalArgumentException Returns an instance ofa proxyclassforthe specified interfaces that dispatchesmethodinvocationstothespecifiedinvocationhandler.
  這個(gè)方法的作用就是得到一個(gè)動(dòng)態(tài)的代理對(duì)象,其接收三個(gè)參數(shù),我們來(lái)看看這三個(gè)參數(shù)所代表的含義:
  loader:一個(gè)ClassLoader對(duì)象,定義了由哪個(gè)ClassLoader對(duì)象來(lái)對(duì)生成的代理對(duì)象進(jìn)行加載
  interfaces:一個(gè)Interface對(duì)象的數(shù)組,表示的是我將要給我需要代理的對(duì)象提供一組什么接口,如果我提供了一組接口給它,那么這個(gè)代理對(duì)象就宣稱實(shí)現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了
  h:一個(gè)InvocationHandler對(duì)象,表示的是當(dāng)我這個(gè)動(dòng)態(tài)代理對(duì)象在調(diào)用方法的時(shí)候,會(huì)關(guān)聯(lián)到哪一個(gè)InvocationHandler對(duì)象上
  好了,在介紹完這兩個(gè)接口(類)以后,我們來(lái)通過(guò)一個(gè)實(shí)例來(lái)看看我們的動(dòng)態(tài)代理模式是什么樣的:
  首先我們定義了一個(gè)Subject類型的接口,為其聲明了兩個(gè)方法:
  publicinterfaceSubject { publicvoidrent(); publicvoidhello(String str); }
  接著,定義了一個(gè)類來(lái)實(shí)現(xiàn)這個(gè)接口,這個(gè)類就是我們的真實(shí)對(duì)象,RealSubject類:
  publicclassRealSubjectimplementsSubject{@Overridepublicvoidrent() { System.out.println(“I want to rent my house”); } @Overridepublicvoidhello(String str) { System.out.println(“hello: ”+ str); } }
  下一步,我們就要定義一個(gè)動(dòng)態(tài)代理類了,前面說(shuō)個(gè),每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn) InvocationHandler 這個(gè)接口,因此我們這個(gè)動(dòng)態(tài)代理類也不例外:
  publicclassDynamicProxyimplementsInvocationHandler{// 這個(gè)就是我們要代理的真實(shí)對(duì)象privateObject subject; // 構(gòu)造方法,給我們要代理的真實(shí)對(duì)象賦初值publicDynamicProxy(Object subject) { this.subject = subject; } @OverridepublicObjectinvoke(Object object, Method method, Object[] args) throwsThrowable { //  在代理真實(shí)對(duì)象前我們可以添加一些自己的操作System.out.println( “before rent house”); System.out.println( “Method:”+ method); // 當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來(lái)進(jìn)行調(diào)用method.invoke(subject, args);//  在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作System.out.println( “after rent house”); returnnull; } }
  最后,來(lái)看看我們的Client類:
  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassClient{publicstaticvoidmain(String[] args) { // 我們要代理的真實(shí)對(duì)象Subject realSubject = newRealSubject(); // 我們要代理哪個(gè)真實(shí)對(duì)象,就將該對(duì)象傳進(jìn)去,最后是通過(guò)該真實(shí)對(duì)象來(lái)調(diào)用其方法的InvocationHandler handler =newDynamicProxy(realSubject); /* * 通過(guò)Proxy的newProxyInstance方法來(lái)創(chuàng)建我們的代理對(duì)象,我們來(lái)看看其三個(gè)參數(shù) * 第一個(gè)參數(shù) handler.getClass().getClassLoader() ,我們這里使用handler這個(gè)類的ClassLoader對(duì)象來(lái)加載我們的代理對(duì)象 * 第二個(gè)參數(shù)realSubject.getClass().getInterfaces(),我們這里為代理對(duì)象提供的接口是真實(shí)對(duì)象所實(shí)行的接口,表示我要代理的是該真實(shí)對(duì)象,這樣我就能調(diào)用這組接口中的方法了 * 第三個(gè)參數(shù)handler, 我們這里將這個(gè)代理對(duì)象關(guān)聯(lián)到了上方的 InvocationHandler 這個(gè)對(duì)象上 */Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject .getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.rent(); subject.hello( “world”); } }
  我們先來(lái)看看控制臺(tái)的輸出:
  $Proxy0 before rent house Method:public abstract voidcom.xiaoluo.dynamicproxy.Subject.rent() I want to rent my house after rent house before rent house Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String) hello:world after rent house
  我們首先來(lái)看看 $Proxy0 這東西,我們看到,這個(gè)東西是由 System.out.println(subject.getClass().getName()); 這條語(yǔ)句打印出來(lái)的,那么為什么我們返回的這個(gè)代理對(duì)象的類名是這樣的呢?
  Subject subject = (Subject)Proxy .newProxyInstance(handler .getClass().getClassLoader(), realSubject .getClass() .getInterfaces(), handler) ;
  可能我以為返回的這個(gè)代理對(duì)象會(huì)是Subject類型的對(duì)象,或者是InvocationHandler的對(duì)象,結(jié)果卻不是,首先我們解釋一下為什么我們這里可以將其轉(zhuǎn)化為Subject類型的對(duì)象?原因就是在newProxyInstance這個(gè)方法的第二個(gè)參數(shù)上,我們給這個(gè)代理對(duì)象提供了一組什么接口,那么我這個(gè)代理對(duì)象就會(huì)實(shí)現(xiàn)了這組接口,這個(gè)時(shí)候我們當(dāng)然可以將這個(gè)代理對(duì)象強(qiáng)制類型轉(zhuǎn)化為這組接口中的任意一個(gè),因?yàn)檫@里的接口是Subject類型,所以就可以將其轉(zhuǎn)化為Subject類型了。
  同時(shí)我們一定要記住,通過(guò) Proxy.newProxyInstance 創(chuàng)建的代理對(duì)象是在jvm運(yùn)行時(shí)動(dòng)態(tài)生成的一個(gè)對(duì)象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運(yùn)行是動(dòng)態(tài)生成的一個(gè)對(duì)象,并且命名方式都是這樣的形式,以$開(kāi)頭,proxy為中,最后一個(gè)數(shù)字表示對(duì)象的標(biāo)號(hào)。
  接著我們來(lái)看看這兩句
  subject.rent();
  subject.hello(“world”);
  這里是通過(guò)代理對(duì)象來(lái)調(diào)用實(shí)現(xiàn)的那種接口中的方法,這個(gè)時(shí)候程序就會(huì)跳轉(zhuǎn)到由這個(gè)代理對(duì)象關(guān)聯(lián)到的 handler 中的invoke方法去執(zhí)行,而我們的這個(gè) handler 對(duì)象又接受了一個(gè) RealSubject類型的參數(shù),表示我要代理的就是這個(gè)真實(shí)對(duì)象,所以此時(shí)就會(huì)調(diào)用 handler 中的invoke方法去執(zhí)行:
  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicObject invoke(Object object, Method method, Object[] args) throwsThrowable { //  在代理真實(shí)對(duì)象前我們可以添加一些自己的操作System.out.println( “before rent house”); System.out.println(“Method:”+ method); // 當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來(lái)進(jìn)行調(diào)用method.invoke(subject, args); //  在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作System.out.println( “after rent house”); returnnull; }
  我們看到,在真正通過(guò)代理對(duì)象來(lái)調(diào)用真實(shí)對(duì)象的方法的時(shí)候,我們可以在該方法前后添加自己的一些操作,同時(shí)我們看到我們的這個(gè) method 對(duì)象是這樣的:
  public abstract void com.xiaoluo.dynamicproxy.Subject.rent() public abstract voidcom.xiaoluo.dynamicproxy.Subject.hello(java .lang.String)
  正好就是我們的Subject接口中的兩個(gè)方法,這也就證明了當(dāng)我通過(guò)代理對(duì)象來(lái)調(diào)用方法的時(shí)候,起實(shí)際就是委托由其關(guān)聯(lián)到的 handler 對(duì)象的invoke方法中來(lái)調(diào)用,并不是自己來(lái)真實(shí)調(diào)用,而是通過(guò)代理的方式來(lái)調(diào)用的。
  這就是我們的java動(dòng)態(tài)代理機(jī)制。
  本篇隨筆詳細(xì)的講解了java中的動(dòng)態(tài)代理機(jī)制,這個(gè)知識(shí)點(diǎn)非常非常的重要,包括我們Spring的AOP其就是通過(guò)動(dòng)態(tài)代理的機(jī)制實(shí)現(xiàn)的,所以我們必須要好好的理解動(dòng)態(tài)代理的機(jī)制。
?

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?
      主站蜘蛛池模板: 日本人善交69xxx| 婷婷综合五月中文字幕欧美| 你懂的欧美| 美女免费视频是黄的| 经典三级一区在线播放| 极品美女啪啪| 人人做人人爽国产视| 精品亚洲国产国拍| 男人cao女人视频在线观看| 一级大片视频| 中文字幕色| 黄色在线观看国产| 午夜日韩在线| 日本黄色爽| 国产亚洲高清在线精品不卡| 在线视频图片小说| 日本全黄视频| 国产精品久久久久免费| 天堂网2018| 欧美3d动漫网站| 日日拍夜夜嗷嗷叫狠狠| 国产在线h| 亚洲国内精品| 久久夜色tv网站免费影院| 97久久人人| 久久天天躁狠狠躁夜夜躁 | 老师受年下高h男| 性夜影院午夜看片| 男人天堂伊人网| 久久黄色录像| 禁漫羞羞入口| 欧美性天天| 曰本裸色私人影院噜噜噜影院| xvideos69日本hd| 亚洲qingse| 新版天堂资源中文在线| 欧美大尺度aaa级毛片| 性午夜影院| 天天综合久久| 亚洲精品视频专区| 五月婷婷之综合激情|