色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

java動態(tài)代理機(jī)制詳解的類和接口描述

大小:0.2 MB 人氣: 2017-09-28 需要積分:1

  在學(xué)習(xí)Spring的時候,我們知道Spring主要有兩大思想,一個是IoC,另一個就是AOP,對于IoC,依賴注入就不用多說了,而對于Spring的核心AOP來說,我們不但要知道怎么通過AOP來滿足的我們的功能,我們更需要學(xué)習(xí)的是其底層是怎么樣的一個原理,而AOP的原理就是java的動態(tài)代理機(jī)制,所以本篇隨筆就是對java的動態(tài)機(jī)制進(jìn)行一個回顧。

  在java的動態(tài)代理機(jī)制中,有兩個重要的類或接口,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和接口是實現(xiàn)我們動態(tài)代理所必須用到的。首先我們先來看看java的API幫助文檔是怎么樣對這兩個類進(jìn)行描述的:

  InvocationHandler:

  InvocationHandler isthe interfaceimplemented bythe invocation handler ofa proxy instance. Eachproxy instance hasan associated invocation handler. When amethodisinvokedonaproxyinstance,themethodinvocationisencodedanddispatchedtotheinvokemethodofitsinvocationhandler.

  每一個動態(tài)代理類都必須要實現(xiàn)InvocationHandler這個接口,并且每個代理類的實例都關(guān)聯(lián)到了一個handler,當(dāng)我們通過代理對象調(diào)用一個方法的時候,這個方法的調(diào)用就會被轉(zhuǎn)發(fā)為由InvocationHandler這個接口的 invoke 方法來進(jìn)行調(diào)用。我們來看看InvocationHandler這個接口的唯一一個方法 invoke 方法:

  Object invoke(Object proxy, Methodmethod, Object[] args) throwsThrowable

  我們看到這個方法一共接受三個參數(shù),那么這三個參數(shù)分別代表什么呢?

  proxy:  指代我們所代理的那個真實對象

  method:  指代的是我們所要調(diào)用真實對象的某個方法的Method對象

  args:  指代的是調(diào)用真實對象某個方法時接受的參數(shù)

  如果不是很明白,等下通過一個實例會對這幾個參數(shù)進(jìn)行更深的講解。

  接下來我們來看看Proxy這個類:

  Proxy provides staticmethods forcreating dynamicproxy classes andinstances, andit isalso the superclass ofall dynamicproxy classes created bythose methods.

  Proxy這個類的作用就是用來動態(tài)創(chuàng)建一個代理對象的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個方法:

  publicstaticObject newProxyInstance(ClassLoader loader, Class《?》[] interfaces, InvocationHandler h) throwsIllegalArgumentException Returns an instance ofa proxyclassforthe specified interfaces that dispatchesmethodinvocationstothespecifiedinvocationhandler.

  這個方法的作用就是得到一個動態(tài)的代理對象,其接收三個參數(shù),我們來看看這三個參數(shù)所代表的含義:

  loader:一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進(jìn)行加載

  interfaces:一個Interface對象的數(shù)組,表示的是我將要給我需要代理的對象提供一組什么接口,如果我提供了一組接口給它,那么這個代理對象就宣稱實現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了

  h:一個InvocationHandler對象,表示的是當(dāng)我這個動態(tài)代理對象在調(diào)用方法的時候,會關(guān)聯(lián)到哪一個InvocationHandler對象上

  好了,在介紹完這兩個接口(類)以后,我們來通過一個實例來看看我們的動態(tài)代理模式是什么樣的:

  首先我們定義了一個Subject類型的接口,為其聲明了兩個方法:

  publicinterfaceSubject { publicvoidrent(); publicvoidhello(String str); }

  接著,定義了一個類來實現(xiàn)這個接口,這個類就是我們的真實對象,RealSubject類:

  publicclassRealSubjectimplementsSubject{@Overridepublicvoidrent() { System.out.println(“I want to rent my house”); } @Overridepublicvoidhello(String str) { System.out.println(“hello: ”+ str); } }

  下一步,我們就要定義一個動態(tài)代理類了,前面說個,每一個動態(tài)代理類都必須要實現(xiàn) InvocationHandler 這個接口,因此我們這個動態(tài)代理類也不例外:

  publicclassDynamicProxyimplementsInvocationHandler{// 這個就是我們要代理的真實對象privateObject subject; // 構(gòu)造方法,給我們要代理的真實對象賦初值publicDynamicProxy(Object subject) { this.subject = subject; } @OverridepublicObjectinvoke(Object object, Method method, Object[] args) throwsThrowable { //  在代理真實對象前我們可以添加一些自己的操作System.out.println( “before rent house”); System.out.println( “Method:”+ method); // 當(dāng)代理對象調(diào)用真實對象的方法時,其會自動的跳轉(zhuǎn)到代理對象關(guān)聯(lián)的handler對象的invoke方法來進(jìn)行調(diào)用method.invoke(subject, args);//  在代理真實對象后我們也可以添加一些自己的操作System.out.println( “after rent house”); returnnull; } }

  最后,來看看我們的Client類:

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassClient{publicstaticvoidmain(String[] args) { // 我們要代理的真實對象Subject realSubject = newRealSubject(); // 我們要代理哪個真實對象,就將該對象傳進(jìn)去,最后是通過該真實對象來調(diào)用其方法的InvocationHandler handler =newDynamicProxy(realSubject); /* * 通過Proxy的newProxyInstance方法來創(chuàng)建我們的代理對象,我們來看看其三個參數(shù) * 第一個參數(shù) handler.getClass().getClassLoader() ,我們這里使用handler這個類的ClassLoader對象來加載我們的代理對象 * 第二個參數(shù)realSubject.getClass().getInterfaces(),我們這里為代理對象提供的接口是真實對象所實行的接口,表示我要代理的是該真實對象,這樣我就能調(diào)用這組接口中的方法了 * 第三個參數(shù)handler, 我們這里將這個代理對象關(guān)聯(lián)到了上方的 InvocationHandler 這個對象上 */Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject .getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.rent(); subject.hello( “world”); } }

  我們先來看看控制臺的輸出:

  $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

  我們首先來看看 $Proxy0 這東西,我們看到,這個東西是由 System.out.println(subject.getClass().getName()); 這條語句打印出來的,那么為什么我們返回的這個代理對象的類名是這樣的呢?

  Subject subject = (Subject)Proxy .newProxyInstance(handler .getClass().getClassLoader(), realSubject .getClass() .getInterfaces(), handler) ;

  可能我以為返回的這個代理對象會是Subject類型的對象,或者是InvocationHandler的對象,結(jié)果卻不是,首先我們解釋一下為什么我們這里可以將其轉(zhuǎn)化為Subject類型的對象?原因就是在newProxyInstance這個方法的第二個參數(shù)上,我們給這個代理對象提供了一組什么接口,那么我這個代理對象就會實現(xiàn)了這組接口,這個時候我們當(dāng)然可以將這個代理對象強(qiáng)制類型轉(zhuǎn)化為這組接口中的任意一個,因為這里的接口是Subject類型,所以就可以將其轉(zhuǎn)化為Subject類型了。

  同時我們一定要記住,通過 Proxy.newProxyInstance 創(chuàng)建的代理對象是在jvm運(yùn)行時動態(tài)生成的一個對象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運(yùn)行是動態(tài)生成的一個對象,并且命名方式都是這樣的形式,以$開頭,proxy為中,最后一個數(shù)字表示對象的標(biāo)號。

  接著我們來看看這兩句

  subject.rent();

  subject.hello(“world”);

  這里是通過代理對象來調(diào)用實現(xiàn)的那種接口中的方法,這個時候程序就會跳轉(zhuǎn)到由這個代理對象關(guān)聯(lián)到的 handler 中的invoke方法去執(zhí)行,而我們的這個 handler 對象又接受了一個 RealSubject類型的參數(shù),表示我要代理的就是這個真實對象,所以此時就會調(diào)用 handler 中的invoke方法去執(zhí)行:

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicObject invoke(Object object, Method method, Object[] args) throwsThrowable { //  在代理真實對象前我們可以添加一些自己的操作System.out.println( “before rent house”); System.out.println(“Method:”+ method); // 當(dāng)代理對象調(diào)用真實對象的方法時,其會自動的跳轉(zhuǎn)到代理對象關(guān)聯(lián)的handler對象的invoke方法來進(jìn)行調(diào)用method.invoke(subject, args); //  在代理真實對象后我們也可以添加一些自己的操作System.out.println( “after rent house”); returnnull; }

  我們看到,在真正通過代理對象來調(diào)用真實對象的方法的時候,我們可以在該方法前后添加自己的一些操作,同時我們看到我們的這個 method 對象是這樣的:

  public abstract void com.xiaoluo.dynamicproxy.Subject.rent() public abstract voidcom.xiaoluo.dynamicproxy.Subject.hello(java .lang.String)

  正好就是我們的Subject接口中的兩個方法,這也就證明了當(dāng)我通過代理對象來調(diào)用方法的時候,起實際就是委托由其關(guān)聯(lián)到的 handler 對象的invoke方法中來調(diào)用,并不是自己來真實調(diào)用,而是通過代理的方式來調(diào)用的。

  這就是我們的java動態(tài)代理機(jī)制。

  本篇隨筆詳細(xì)的講解了java中的動態(tài)代理機(jī)制,這個知識點(diǎn)非常非常的重要,包括我們Spring的AOP其就是通過動態(tài)代理的機(jī)制實現(xiàn)的,所以我們必須要好好的理解動態(tài)代理的機(jī)制。

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

      發(fā)表評論

      用戶評論
      評價:好評中評差評

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

      ?
      主站蜘蛛池模板: 亚洲免费中文 | 我强进了老师身体在线观看 | 久久AV国产麻豆HD真实乱 | 国产精品系列在线一区 | 亚洲精品网址 | 桃花免费高清在线观看 | 在线黑人抽搐潮喷 | AV天堂AV亚洲啪啪久久无码 | 亚洲色综合中文字幕在线 | 伊人青青久久 | 黄色888 | 67194成网页发布在线观看 | 亚洲精品一区三区三区在线观看 | 乌克兰黄色录像 | jzz大全18| 精品免费在线视频 | 5G在线观看免费年龄确认 | 国产精品96久久久久久AV不卡 | 亚洲这里只有精品 | 热re99久久精品国99热 | 翁公咬着小娇乳H边走边欢A | 99精品福利视频 | 22eee在线播放成人免费视频 | 久久4k岛国高清一区二区 | 久久精品美女 | 欧美性色xo影院69 | 手机在线观看无码日韩视频 | 中文无码第3页不卡av | av天堂影音先锋在线 | 欧美亚洲精品真实在线 | 性啪啪chinese东北女人 | 青娱乐极品视觉盛宴av | 国产精品免费视频播放 | 879影视动漫h免费观看 | 伊人大香线蕉精品在线播放 | 老司机福利视频一区在线播放 | 十次啦中文网 | 免费国产久久啪久久爱 | 男人插曲女人的视频 | 中文字幕 日韩 无码 在线 | 中文国产乱码在线人妻一区二区 |