代理模式是一個十分優秀的軟件架構模式,許多應用都用到了代理模式。代理模式就是為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不合適或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
這次主要講解一下代理模式的實例、解決的問題部分。
在java框架中有一種框架就用到了動態代理模式,spring框架中的aop技術,基于代理模式。下面我將以beforeAdvice來進行這個模式的介紹。
這張圖反映了參與到AOP過程中的幾個關鍵組件(以@Before Advice為例):
調用者Beans - 即調用發起者,它只知道目標方法所在Bean,并不清楚代理以及Advice的存在
目標方法所在Bean - 被調用的目標方法
生成的代理 - 由Spring AOP為目標方法所在Bean生成的一個代理對象
Advice - 切面的執行邏輯
它們之間的調用先后次序反映在上圖的序號中:
調用者Bean嘗試調用目標方法,但是被生成的代理截了胡
代理根據Advice的種類(本例中是@Before Advice),對Advice首先進行調用
代理調用目標方法
返回調用結果給調用者Bean(由代理返回,沒有體現在圖中)
在使用Spring AOP的時候可能會遇到的一個問題。類似這種間接調用不會觸發Advice的原因在于調用發生在目標方法所在Bean的內部,和外面的代理對象可是沒有半毛錢的關系哦。我們可以把這個代理想象成一個中介,只有它知道Advice的存在,調用者Bean和目標方法所在Bean知道彼此的存在,但是對于代理或者是Advice卻是一無所知的。因此,沒有通過代理的調用是絕無可能觸發Advice的邏輯的。
代理模式的應用場景還有延遲加載場景,延遲加載的思想:如果當前沒有使用這個組件時,則不需要真正地去初始化它,而是用一個代理對象去替代它的原有位置。當真正需要使用的時候,才對它進行加載。使用代理模式實現延遲加載是很有意義的,首先從時間軸上分散系統的壓力,尤其在系統啟動時,不必完成所有的初始化工作,從而加速啟動時間;其次,對于很多真事主題而言,在軟件啟動到系統關閉的整個過程,可能都不會被調用,初始化這些數據無疑是一種資源的浪費。
假設某客戶端軟件,根據用戶請求,去數據庫查詢數據的功能。在數據庫查詢前需要獲得數據庫連接。在系統啟動時,初始化系統所有的類,此時嘗試獲得數據庫連接。當系統存在大量類似的操作時(XML解析等),所有這些初始化操作都必須疊加,使得系統很慢。為此,使用代理模式,使用代理類,封裝對數據庫的查詢操作。當系統啟動時,初始化這個代理類,而非真實的數據庫查詢類,而代理類什么都不做。當真正開始查詢的時候,才初始化查詢對象。
代理模式的應用場景主要還是分為4類:
遠程代理:為一個對象在不同地址空間提供局部代表。這樣可以隱藏一個對象存在于不同地址空間的事實,例如:老阮(MrRuan)在地點A,老李在地點B,餐廳柜臺也在地點B,那么老李和老軟住在一起(都在地點A住),那么老李就是餐廳(地點B)在老軟與老李住處(地點A)的代表。
虛擬代理:是根據需要創建開銷很大的對象。通過它來存放實例化需要很長時間的真是對象,例如:老阮(MrRuan)在地點A,到餐廳柜臺(地點B),因為距離遠卻是很費勁,而老李剛好在這里(地點B)上班,所以讓老李去辦是很可行的辦法。(不太恰當) 安全代理:用來控制真是對象訪問時的權限,例如:老阮跟餐廳的柜臺MM剛分手不方便去辦理,所以需要借助老李去完成事項的辦理。 智能代理:是指當調用真是的對象時,代理去處理另外一些事情,例如:老李幫助老阮辦理卡片激活時,順便說說老阮的好話,讓她倆能夠和好。
WebService也是應用到了代理模式,我們來看一下WebService的示例過程:
實現一個完整的Web服務包括以下步驟:
◆ Web服務提供者設計實現Web服務,并將調試正確后的Web服務通過Web服務中介者發布,并在UDDI注冊中心注冊; (發布)
◆ Web服務請求者向Web服務中介者請求特定的服務,中介者根據請求查詢UDDI注冊中心,為請求者尋找滿足請求的服務; (發現)
◆ Web服務中介者向Web服務請求者返回滿足條件的Web服務描述信息,該描述信息用WSDL寫成,各種支持Web服務的機器都能閱讀;(發現)
◆ 利用從Web服務中介者返回的描述信息生成相應的SOAP消息,發送給Web服務提供者,以實現Web服務的調用;(綁定)
◆ Web服務提供者按SOAP消息執行相應的Web服務,并將服務結果返回給Web服務請求者。(綁定)
總之,許多都應用到了代理模式,在使用的時候認真查看原理,對代理模式加深自己的理解。


