如何解决代理模式详解的原理详解
?我特意將本系列改了下名字,原名是《設計模式學習之路》,原因是因為之前寫過一篇《spring源碼學習之路》,但是我感覺本次寫二十三種設計模式,更多的還是分享給各位自己的理解,所以感覺學習之路有點不合適,另外,從本章開始,正式啟用本人稱呼,LZ。
? ? ? ? ? ? ? ?好了,廢話至此,本章接著討論第二種要介紹的設計模式,代理模式。
? ? ? ? ? ? ? ?LZ不希望寫的東西與網絡上的資料千篇一律,所以這一系列不會像很多典型文章一章,只是列出這個模式的定義以及一堆適用的情況,然后就是一堆這個模式的各個角色,對于這種羅列LZ并不反對,相比之下會比較清晰,但是如果脫離了實際,就會導致看的人特別是初學者覺得設計模式很陌生很遙遠。
? ? ? ? ? ? ? ?LZ并不反對這種教學式的標準模式,但說實話,LZ本人看這種帖子從來都感覺收獲不大,看一遍看一遍,到現在都沒記住那些各個適用的情況與一堆亂七八糟的角色。
? ? ? ? ? ? ? ?所以LZ探討代理模式,不會再按這個步驟進行,而是跟著自己的思維進行。
? ? ? ? ? ? ? ?首先代理模式,可以分為兩種,一種是靜態代理,一種是動態代理。
? ? ? ? ? ? ? ?兩種代理從虛擬機加載類的角度來講,本質上都是一樣的,都是在原有類的行為基礎上,加入一些多出的行為,甚至完全替換原有的行為。
? ? ? ? ? ? ? ?靜態代理采用的方式就是我們手動的將這些行為換進去,然后讓編譯器幫我們編譯,同時也就將字節碼在原有類的基礎上加入一些其他的東西或者替換原有的東西,產生一個新的與原有類接口相同卻行為不同的類型。
? ? ? ? ? ? ? ?說歸說,我們來真實的去試驗一下,實驗的話需要找一個示例,就拿我們的數據庫連接來做例子吧。
? ? ? ? ? ? ? ?我們都知道,數據庫連接是很珍貴的資源,頻繁的開關數據庫連接是非常浪費服務器的CPU資源以及內存的,所以我們一般都是使用數據庫連接池來解決這一問題,即創造一堆等待被使用的連接,等到用的時候就從池里取一個,不用了再放回去,數據庫連接在整個應用啟動期間,幾乎是不關閉的,除非是超過了最大閑置時間。
? ? ? ? ? ? ? ?但是在程序員編寫程序的時候,會經常使用connection.close()這樣的方法,去關閉數據庫連接,而且這樣做是對的,所以你并不能告訴程序員們說,你們使用連接都不要關了,去調用一個其他的類似歸還給連接池的方法吧。這是不符合程序員的編程思維的,也很勉強,而且具有風險性,因為程序員會忘的。
? ? ? ? ? ? ? ?解決這一問題的辦法就是使用代理模式,因為代理模式可以替代原有類的行為,所以我們要做的就是替換掉connection的close行為。
? ? ? ? ? ? ? ?下面是connection接口原有的樣子,我去掉了很多方法,因為都類似,全貼上來占地方。
[java]?view plain?copy
????????????? 如下所示。
[java]?view plain?copy
? ? ? ? ? ? ? ? 此處為了更形象,LZ給出一個本人寫的非常簡單的連接池,意圖在于表明實現的思路。下面我們來看一下連接池的變化,在里面注明了變化點。
[java]?view plain?copy
? ? ? ? ? ? ? ? 好了,這下我們的連接池返回的連接全是代理,就算程序員調用了close方法也只會歸還給連接池了。
? ? ? ? ? ? ? ??我們使用代理模式解決了上述問題,從靜態代理的使用上來看,我們一般是這么做的。
? ? ? ? ? ? ? ? 1,代理類一般要持有一個被代理的對象的引用。
? ? ? ? ? ? ? ? 2,對于我們不關心的方法,全部委托給被代理的對象處理。
? ? ? ? ? ? ? ? 3,自己處理我們關心的方法。
? ? ? ? ? ? ? ? 這種代理是死的,不會在運行時動態創建,因為我們相當于在編譯期,也就是你按下CTRL+S的那一刻,就給被代理的對象生成了一個不可動態改變的代理類。
? ? ? ? ? ? ? ?靜態代理對于這種,被代理的對象很固定,我們只需要去代理一個類或者若干固定的類,數量不是太多的時候,可以使用,而且其實效果比動態代理更好,因為動態代理就是在運行期間動態生成代理類,所以需要消耗的時間會更久一點。就像上述的情況,其實就比較適合使用靜態代理。
? ? ? ? ? ? ? ?下面介紹下動態代理,動態代理是JDK自帶的功能,它需要你去實現一個InvocationHandler接口,并且調用Proxy的靜態方法去產生代理類。
? ? ? ? ? ? ? ?接下來我們依然使用上面的示例,但是這次該用動態代理處理,我們來試一下看如何做。
[java]?view plain?copy
? ? ? ? ? ? ? ?上述便是我們針對connection做動態代理的方式,但是我們從中得不到任何好處,除了能少寫點代碼以外,因為這個動態代理還是只能代理Connection這一個接口,如果我們寫出這種動態代理的方式的話,說明我們應該使用靜態代理處理這個問題,因為它代表我們其實只希望代理一個類就好。從重構的角度來說,其實更簡單點,那就是在你發現你使用靜態代理的時候,需要寫一大堆重復代碼的時候,就請改用動態代理試試吧。
? ? ? ? ? ? ? ?通常情況下,動態代理的使用是為了解決這樣一種問題,就是我們需要代理一系列類的某一些方法,最典型的應用就是我們前段時間討論過的springAOP,我們需要創造出一批代理類,切入到一系列類當中的某一些方法中。下面給出一個經常使用的動態代理方式。
[java]?view plain?copy
? ? ? ? ? ? ? ??動態代理有一個強制性要求,就是被代理的類必須實現了某一個接口,或者本身就是接口,就像我們的Connection。
? ? ? ? ? ? ? ? 道理其實很簡單,這是因為動態代理生成的代理類是繼承Proxy類的,并且會實現被你傳入newProxyInstance方法的所有接口,所以我們可以將生成的代理強轉為任意一個代理的接口或者Proxy去使用,但是Proxy里面幾乎全是靜態方法,沒有實例方法,所以轉換成Proxy意義不大,幾乎沒什么用。假設我們的類沒有實現任何接口,那么就意味著你只能將生成的代理類轉換成Proxy,那么就算生成了,其實也沒什么用,而且就算你傳入了接口,可以強轉,你也用不了這個沒有實現你傳入接口的這個類的方法。
? ? ? ? ? ? ? ?你可能會說,假設有個接口A,那我將接口A傳給newProxyInstance方法,并代理一個沒實現接口A的類B,但類B與接口A有一樣的方法可以嗎?
? ? ? ? ? ? ? ?答案是可以的,并且JDK的動態代理只認你傳入的接口,只要你傳入,你就可以強轉成這個接口,這個一會解釋,但是你無法在invoke方法里調用method.invoke方法,也就是說,你只能全部替換A接口的方法,而不能使用類B中原有與接口A方法描述相同的方法,這是因為invoke中傳入的Method的class信息是接口A,而類B因為沒實現接口A,所以無法執行傳入的Method,會拋出非法參數異常。
? ? ? ? ? ? ? ?下面我貼出測試代碼,各位可以自己試一下,具體為何會這樣是在后面解釋的,這里不再多做解釋。
? ? ? ? ? ? ? 先是一個普通接口。
[java]?view plain?copy
? ? ? ? ? ? 然后是一個類,和接口一模一樣的方法,但是就是沒實現這個接口。
[java]?view plain?copy
[java]?view plain?copy
[java]?view plain?copy
? ? ? ? ? ? ? ?上面寫這個例子只是為了解釋LZ當初的疑惑,因為LZ曾一度認為不實現接口就不能使用動態代理,現在想想那時候LZ有點2,呵呵。
? ? ? ? ? ? ? ?好了,從現在開始,我們開始詳細講解動態代理的原理,這算是進階篇,如果是新手的話,可以跳過下面的內容,因為現在還沒必要知道這些,而且弄不好會越看越蒙,不過僅僅是LZ個人建議,你要有耐心,完全可以繼續看下去。
? ? ? ? ? ? ? ?接下來我們結合源碼去看一下,代理類是如何產生的,首先當然就是要進入Proxy的newProxyInstance方法,這里是產生代理的入口,源碼如下。
[java]?view plain?copy
(完)
http://ji63658820.blog.sohu.com/
http://zhizhi01417.blog.sohu.com/
http://baquanzhaojiure.blog.sohu.com/
http://kenchi0072.blog.sohu.com/
http://zifang439602.blog.sohu.com/
http://gongpuzhishuozh.blog.sohu.com/
http://qiaoxun78874.blog.sohu.com/
http://juyukehuazai.blog.sohu.com/
http://naoqun271707.blog.sohu.com/
http://ranghui584859.blog.sohu.com/
http://kan85274856.blog.sohu.com/
http://jidou50557525.blog.sohu.com/
http://yunqun25200989.blog.sohu.com/
http://pangcao9153130.blog.sohu.com/
http://koufuyi599899.blog.sohu.com/
http://sifan76579.blog.sohu.com/
http://xian40097124.blog.sohu.com/
http://zhengdi824808.blog.sohu.com/
http://huiyuan30898.blog.sohu.com/
http://tuzhi052086.blog.sohu.com/
http://zigan813704.blog.sohu.com/
http://aopu127791.blog.sohu.com/
http://zhixun2111431.blog.sohu.com/
http://yonglu5882289.blog.sohu.com/
http://blog.sohu.com/home/news/index.htm
http://shi05778335.blog.sohu.com/
http://duntao5889640.blog.sohu.com/
http://ying56663881.blog.sohu.com/
http://miyou1chao.blog.sohu.com/
http://quebeng9112.blog.sohu.com/
http://langpai3822036.blog.sohu.com/
http://shangguai483499.blog.sohu.com/
http://jiaoyi97308.blog.sohu.com/
http://shazhun795212.blog.sohu.com/
http://fufang6180765.blog.sohu.com/
http://xianlekangkao.blog.sohu.com/
http://duxing0651.blog.sohu.com/
http://tuohaoba022375.blog.sohu.com/
http://yuji3gui153382.blog.sohu.com/
http://zemu1426600.blog.sohu.com/
http://yacang160402.blog.sohu.com/
http://gua20742393.blog.sohu.com/
http://jisuweichun.blog.sohu.com/
http://pudu6738715.blog.sohu.com/
http://leitou52561606.blog.sohu.com/
http://dicisixian.blog.sohu.com/
http://dituo654174.blog.sohu.com/
http://tutuo81160508.blog.sohu.com/
http://guaqiaotushuqin.blog.sohu.com/
http://tanjiaju772135.blog.sohu.com/
http://xia22401507.blog.sohu.com/
http://pojiao2520371.blog.sohu.com/
http://chicurangou.blog.sohu.com/
http://luzaweituan.blog.sohu.com/
http://chengfen860412.blog.sohu.com/
http://poba73704219.blog.sohu.com/
http://mei89825164.blog.sohu.com/
http://duang32836452.blog.sohu.com/
http://jiubei390139.blog.sohu.com/
http://xieraoqiefankao.blog.sohu.com/
http://yilang47832.blog.sohu.com/
http://sijiao2818166.blog.sohu.com/
http://lutong084166.blog.sohu.com/
http://yunbai038826.blog.sohu.com/
http://chuishao96160.blog.sohu.com/
http://duanao45202.blog.sohu.com/
http://zena58309333.blog.sohu.com/
http://zhaopouga.blog.sohu.com/
http://jijiziluzi.blog.sohu.com/
http://youmu86072747.blog.sohu.com/
http://yiqiao0799346.blog.sohu.com/
http://fangqiang2gong.blog.sohu.com/
http://luxuan5003.blog.sohu.com/
http://lanlue1673873.blog.sohu.com/
http://wopiao8981.blog.sohu.com/
http://yiliezhiyun.blog.sohu.com/
http://zenxunaozhundi.blog.sohu.com/
http://xionggong001752.blog.sohu.com/
http://zhichenlintugui.blog.sohu.com/
http://queyi41528049.blog.sohu.com/
http://jiejia423144.blog.sohu.com/
http://shaogangliaoqin.blog.sohu.com/
http://jiuchun3411223.blog.sohu.com/
http://jiaoba81253.blog.sohu.com/
http://fangjiao495408.blog.sohu.com/
http://fuqiang376.blog.sohu.com/
http://zouhuiyongtanch.blog.sohu.com/
http://xiqiao92002.blog.sohu.com/
http://shu82355473.blog.sohu.com/
http://ziyuan254736.blog.sohu.com/
http://sitan4pi158934.blog.sohu.com/
http://jueyan6xia.blog.sohu.com/
http://dongliang43145.blog.sohu.com/
http://yiwei71321060.blog.sohu.com/
http://cizhuang49210.blog.sohu.com/
http://fenpan87260.blog.sohu.com/
http://xiyo0267815.blog.sohu.com/
http://yingrong5mei.blog.sohu.com/
http://jingtong2234.blog.sohu.com/
http://tuikang744040.blog.sohu.com/
http://depaisiyi.blog.sohu.com/
http://olu5514216.blog.sohu.com/
http://gou86478183.blog.sohu.com/
http://weiyuan1song.blog.sohu.com/
http://jiaoxia718784.blog.sohu.com/
http://taoji03753000.blog.sohu.com/
http://zhunpanxianyunf.blog.sohu.com/
http://linyediweijiang.blog.sohu.com/
http://lanyi47493068.blog.sohu.com/
http://bidui003324.blog.sohu.com/
http://xunqie35956392.blog.sohu.com/
http://puyi22288.blog.sohu.com/
http://jiazhe3155.blog.sohu.com/
http://gan82261201.blog.sohu.com/
http://jiazhe3155.blog.sohu.com/
http://yong06919851.blog.sohu.com/
http://qinlin934705.blog.sohu.com/
http://zhangji762369.blog.sohu.com/
http://xinhan954.blog.sohu.com/
http://ozhishangba.blog.sohu.com/
http://shaxin5933667.blog.sohu.com/
http://jiuyazhijidi.blog.sohu.com/
http://ji00478205.blog.sohu.com/
http://daoxian5666001.blog.sohu.com/
http://duxuan1146.blog.sohu.com/
http://xiegui137392.blog.sohu.com/
http://jiuao92856238.blog.sohu.com/
http://pusong8394.blog.sohu.com/
http://jidao8227035.blog.sohu.com/
http://shiqi625077.blog.sohu.com/
http://chijia501914.blog.sohu.com/
http://zhongshi537706.blog.sohu.com/
http://zhanglu4738465.blog.sohu.com/
http://shuojia670.blog.sohu.com/
http://ke63240682.blog.sohu.com/
http://rangyongziliang.blog.sohu.com/
http://xunshan7916.blog.sohu.com/
http://nacong632878.blog.sohu.com/
http://dumeihailazhuan.blog.sohu.com/
http://langao48260378.blog.sohu.com/
http://tulan64540.blog.sohu.com/
http://qinqiang5si.blog.sohu.com/
http://langren750634.blog.sohu.com/
http://tuoshou730823.blog.sohu.com/
http://beixian305396.blog.sohu.com/
http://koutuomeijingtu.blog.sohu.com/
http://kehui0240677.blog.sohu.com/
http://han36991002.blog.sohu.com/
http://huituo863.blog.sohu.com/
http://youqun0rang.blog.sohu.com/
http://pujiu3104779.blog.sohu.com/
http://jiuba0958174.blog.sohu.com/
http://fugu1860309345.blog.sohu.com/
http://bazhi047569.blog.sohu.com/
http://wogan4515.blog.sohu.com/
http://chuncheng1chao.blog.sohu.com/
http://qingcheng367532.blog.sohu.com/
http://linshanyeanhan.blog.sohu.com/
http://jushi7pa051073.blog.sohu.com/
http://za67896020.blog.sohu.com/
http://jiehui5chi.blog.sohu.com/
http://yongtuo61728.blog.sohu.com/
http://daofu64180926.blog.sohu.com/
http://jizhuo0huan.blog.sohu.com/
http://ziren3128194.blog.sohu.com/
http://fuqiangrangxia.blog.sohu.com/
http://yunbu5jue.blog.sohu.com/
http://hejiao9593454.blog.sohu.com/
http://poyeduhai.blog.sohu.com/
http://zhan37581019.blog.sohu.com/
http://laotan164675.blog.sohu.com/
http://xieqinkaoche.blog.sohu.com/
http://liaorao0254.blog.sohu.com/
http://koucong9mei.blog.sohu.com/
http://pamu6355864.blog.sohu.com/
http://jiaotuo350363.blog.sohu.com/
http://bachun6523.blog.sohu.com/
http://sike461935.blog.sohu.com/
http://latuan317871.blog.sohu.com/
http://konglan6560643.blog.sohu.com/
[ja
總結
以上是生活随笔為你收集整理的如何解决代理模式详解的原理详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mac 下安装 Crypto
- 下一篇: 海量辅助无限多开 就在新浪页游助手