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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用Delphi实现动态代理(2):设计说明

發布時間:2024/1/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Delphi实现动态代理(2):设计说明 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用Delphi實現動態代理(2):設計說明

[Mental Studio]猛禽[Blog]

在上篇《用Delphi實現動態代理(1):概述》中,對動態代理作了一個概要的說明,比如為什么需要這樣的動態代理,它有什么用等。本篇將對我實現的這個動態代理的設計思路作一下介紹。
?

一、設計目標

如上篇中這幅動態代理結構圖所示:

大致的設計目標有以下幾項:

  • TMDynamicProxy可以將任意接口代理到一個通用接口IMInvocationHandler上;
  • IMInvocationHandler的實現不能太復雜,即TMMethodInvocation的定義要盡量簡單;
  • IMInvocationHandler要能夠實現Remoting,即TMMethodInvocation必須可序列化;
  • 需要一個IMMethodInterceptor接口,以便于實現AOP所需要的各種攔截器;
  • 需要一個TMInterfaceInvoker來把IMInvocationHandler轉為正確的對象調用。

從上面列出的目標可以看出,我的目標是要實現一套全新的多層框架,并且幾乎是對JAVA世界里最流行的輕量容器的模仿。接下來就說明一下原因所在。
?

二、原因

我之所以對這個動態代理如此熱情,源自于對DELPHI下多層技術的憤怒。想想從前在DELPHI開發多層應用有些什么?MIDAS?不可否認,MIDAS是一項很優秀的開發技術,可以在很大程度上簡化多層應用的開發。但是正因為它的簡單化,所以它跟RAD一樣,容易讓人在簡單化中迷失,而看不到問題的本質--對于這種事情,我喜歡引用老鄭鐘道新的一個經典比喻:(比基尼泳裝展示了令人感興趣的部分,但卻隱藏了關鍵的部分所顯示的是讓人感興趣的部分,所掩蓋的則是關鍵的部分(剛找到這句話的準確出處,特此糾正)。這導致的結果就是開發出大量的垃圾多層應用--至少跟大部分JAVA或CORBA多層應用相比是這樣的。

雖然李維寫了《Delphi 5.x多層分布式應用》系列三本書,試圖深入地解析一下MIDAS,但是一方面是在這浮躁的氛圍下大多數人沒有心思深入研究,另一方面則是MIDAS的先天不足。

上圖是我在2001年寫的一份書稿[1]里的一幅插圖,基本上可以說明MIDAS的整體結構,從圖上可以看出MIDAS沒有自己的基礎技術。

其中DCOM、Socket/TCP、Web/HTTP三種連接方式,本質上還是通過COM技術實現的。Socket和Web連接是借助于ScktSrvr和HttpSrvr兩個代理程序在服務端與客戶端之間建立一個Tunnel來繞過Windows的安全機制或是Firewall。在這樣的應用中,Remoting是靠DCOM的ORPC實現,Transactional Data Module服務端的事務處理、Pooling則是交由MTS/COM+ Container實現,而如果是用Remote Data Module/DCOM的話,則得不到這些方面的支持。

那么用CORBA連接的MIDAS呢?在后來版本的DELPHI中--大約是D5或D6開始--取消了這一支持。如果我沒記錯的話,在D4中的CORBA/MIDAS實現也是基于COM技術的。

最值得一提的是D6開始的SOAP支持,在這里,DELPHI終于提供了一個自己的Remoting實現,也是本文所要討論的動態代理。不過遺憾的是,這里用的動態代理并沒有被做成通用的東西,而是專門為SOAP實現定制了一個,與DELPHI的SOAP實現緊密捆綁。

正因為以上所說的原因,當Kylix出現時,我們面臨著在非Windows平臺下沒有MIDAS的困境。雖然這并非絕境,至少還可以用SOAP/MIDAS,或是純正的CORBA。遺憾的是SOAP的性能太差,而CORBA--且不說OMG沒有提供IDL2PAS的標準--還面臨著復雜性的問題。
?

三、為什么要模仿JAVA

我選擇JAVA作為模仿對象的一個原因是我認為:DELPHI需要一個像RMI這樣的Remoting技術。

目前流行的Remoting技術有兩類:

  • 一是類似于CORBA/DCOM這樣的跨語言技術,這樣技術需要使用“代碼生成”--比如CORBA,需要先寫一個定義遠程對象的IDL文件,然后通過ORB提供的IDL編譯器來生成具體語言的Stub/Skeleton代碼;DCOM也類似,需要先寫一個MIDL(DELPHI中使用TypeLib Editor實現可視化編輯)來定義服務端對象,生成服務端接口代碼,編譯服務端程序時,MIDL也被編譯成TypeLib并以資源形式鏈接到服務端程序里;
  • 另一種是類似于RMI這樣的獨有技術,Remoting的實現依賴于語言本身的動態特性或由平臺提供(如.net remoting)。比如RMI,將接口實現從RemoteObject派生即可為接口提供遠程訪問的語義。

顯然,RMI雖然犧牲了跨語言的優勢(其實RMI可以通過RMI over IIOP實現與CORBA的互操作,并沒有完全犧牲這一優勢),但同時也避免了“代碼生成”,這是一個很大的好處。

對于“代碼生成”這一惡行,我是深有體會的。去年我在試圖開發一個基于XML的WEB框架時,一直是用DELPHI提供的XML Data binding來做的。基本的做法是:先用工具(如XMLSPY)做好一個XML Schema(XSD),然后用XML Data binding wizard生成DELPHI的接口和類。當然,一旦生成就可以很方便地使用了,只要在程序里操作這些接口就好了,其中各個Field都會被變成屬性,并且類型也都如XSD中的定義。但問題在于程序在開發過程中,總是會有一些變化的,在這種情況下,就不得不同時開著XMLSPY修改XSD,然后重新用XML Data binding的Wizard跑一遍,非常的麻煩。做過CORBA開發的人大概也會有類似這樣的體會。雖然在DELPH下做COM開發很方便,有一個可視化的TypeLib Editor可以用,但是還是不爽。

當然,如果是在“理想”的“軟件藍領”環境里,那大概要幸福得多,因為交到Coder手里的接口已經是基本上定死,照著文檔做就是了,沒有這樣的煩惱。但對于Agiler們,這樣的麻煩是不可忍受的。

模仿JAVA的另一個原因是我對非侵入的輕量級容器的向往。所謂輕量級和重量級,是相對而言的,評價的標準就是系統對用戶代碼的侵入性大小。

先來看看一個侵入性強的例子。比如一個典型的MTS/COM+應用,用戶代碼除了要實現自己定義的業務邏輯接口以外,還至少必須要實現IObjectControl接口。另外,還必須通過ObjectContext與容器進行互動,比如通過IObjectContext接口進行基本的事務和安全性操作;如果要更進一步操作事務,還要通過ITransactionContext;要進行更多安全性操作,還要通過ISecurityProperty接口等。

可以看到,像事務處理、安全性檢查這些都是屬于基礎設施的部分,與用戶的業務邏輯沒有一點關系,但是這些部分又是“橫切”于用戶系統結構,與用戶代碼緊密交織在一起。而且更重要的是這些的控制權都掌握在容器框架手上,用戶只能按框架的要求來做,比如MTS/COM+的安全性控制就是與Windows的域用戶管理機制緊密捆綁。這帶來很大的學習成本,低的靈活性,以及開發的復雜性。

為此,專家們提出了AOP的思想。AOP即Aspect Oriented Programming,面向方面編程。但AOP并不是一種要取代OOP的新技術,而是對OOP處理“橫切”問題的一個補充。經典的OOP處理“橫切”問題通常是采用Template Method模式或類似的方法來解決,結果就是導致了強侵入性的框架。

基于AOP的思路,非侵入的框架應運而生。

一個典型的非侵入的框架中,用戶代碼始終是像下面這么簡潔明了:

// 業務邏輯定義
{$M+}
IBizIntf = Interface
['{3A85E46D-F3D4-4D9C-A06C-4E7C1BAC9361}']
// 定義業務邏輯
End;
{$M-}

// 服務端業務邏輯實現
TBizImpl = class(TInterfacedObject, IBizIntf)
Protected
// 實現業務邏輯
end;

// 客戶端調用代碼
Var
BizObj : IBizIntf;
BizObj := TMDynamicProxy( TypeInfo( IBizIntf ), RemoteHandler ) As IBizIntf;
BizObj.xxx // 直接操作服務端對象

在這樣的應用中,業務邏輯定義是用DELPHI原生的接口,而不需要另外的像IDL或TypeLib之類,這樣整個開發過程都可以在DELPHI語言的范圍,用戶代碼的開發也可以將注意力完全集中在業務邏輯的處理上。

但光有AOP的思想是不夠的,還需要有實現。最初的實現是像AspectJ,在JAVA代碼編譯前作一次預編譯,將Aspect代碼織入后再用JAVA編譯器編譯成ByteCode。遺憾的是,這也是一種“代碼生成”技術。后來一個叫Jon Tirsen的人利用動態代理設計了一種運行時織入Aspect的實現--Naning[2]。

使用這種動態織入的Interceptor技術,框架提供的附加服務都可以通過Interceptor進行切入。不論是Remoting、事務、安全性,都可以做成相應的Interceptor,然后通過配置或代碼在運行時動態地將所需的Interceptor織入來實現所需要的功能。

而這一切的核心,還是“動態代理”。


參考文獻
[1]此書已經夭折,引用的插圖出自已經完成的第四章,在這里下載。
[2]透明《動態代理的前世今生》(《程序員》2005年第1期)

附:我用DELPHI實現的動態代理代碼可以在這里下載,還在改進中,僅供參考。(鏈接已更新)

[Mental Studio]猛禽 Feb.28-05, Mar.01

總結

以上是生活随笔為你收集整理的用Delphi实现动态代理(2):设计说明的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。