如今的程序員,其審美觀何等挑剔,差異又何等巨大,然ASP.NET這位美女卻獨領風騷,何哉?大凡我們說某某某“美”,如果是外在的美,那總是經不起時間的考驗和眾人對美的差異定位,而如果是內在美,則時間無法洗去其氣質,眾人亦無旁詞。故欲知ASP.NET美之何在,當瞧其內在,方可知曉。
我在CSDN上逛的時候,無意中發現了《[翻譯]了解ASP.NET底層架構.doc》這篇文章,看完之后,一頭霧水,但又似乎意猶未盡,于是耐心下來,對于每一處有疑點的地方慢慢琢磨,查資料,向我的同事也是好友qwliang請教,(我的很多疑惑點正是因為有他的指導和幫助才得以得到解決,謝謝他)。反反復復的看了幾遍,終于看懂了這篇文章,也“瞧”見了ASP.NET的美。
我本來想針對自己已經形成的理解寫一個系列,但是考慮到近期時間比較緊,而且最終寫出來的東西,大多還是“剪刀+口水”的產物,還不如把自己的在分析分析asp.net底層運行原理過程中,搜索到的比較有價值的一些資料共享上來,大家“仁者見仁,智者見智”。我在后面附帶介紹自己對這些文章的評價,希望能幫助你理解分析。
在分析的過程當中,充分利用Reflector是必要的。因為通過它,你可以看到實際的代碼(盡管不一定和源代碼一模一樣)。如果說文字是有二義性的,那么,代碼是沒有的,通過分析代碼,你可以更容易理解文字表達的內容。
另外,附上我的一些個人認識:
1 幾個名詞解釋:
A: XX工廠(Factory):生成某個對象運用了工廠模式,負責生成(生產)對象任務的對象叫做工廠。工廠模式是一種構建模式,通過附件2你應該能夠理解。
B: CLR寄宿(Host) :不要被這個名詞嚇倒,其實沒有什么,CLR寄宿,實際上就是在非托管應用程序中加載CLR。一個非托管應用程序(比如sql server2005)需要運行托管代碼(比如C#寫的存儲過程),那么就需要在它的進程當中加載.NET運行時CLR,也就是說CLR要寄宿在運行sql server的進程當中。
其實,從生活中來看“寄宿”這個詞也可以幫助你理解。假如你和你的家人住在一起,那我們不會說你寄宿在你家,如果哪天你來了一個遠房親戚住在你家,他就是寄宿在你家。對于一個托管程序,你用Dependency這個工具來看,你會發現,它的運行要依賴于MsCoree.dll,而對于一個非托管程序,則應該不會看到這個依賴(Dependency只能看到靜態依賴關系),因為寄宿CLR一般是通過LoadLibrary來動態加載的(這個我不敢肯定,但是我看了好幾個.exe和.dll都沒有,比如w3wp.exe,inetInfo.exe等)。
關于寄宿的細節,你可以參考《.NET框架程序設計》(修訂版)中的1.3節《加載.net運行時》和20.2《CLR寄宿》。
C: 應用程序域(AppDomain):應用程序域從邏輯上來說,它類似于進程,它是一個邏輯上的容器?!坝颉钡母拍?,其實也就是一個范圍的概念,就好像以前的跑馬圈地,圈住一塊地之后就說這是我的地域范圍。從實現上來說,AppDomain也是System命名空間中的一個類,你可以通過Reflector看到這個類的信息。你也可以參考《.NET框架程序設計》(修訂版)中的20.3《應用程序域》。
D: 容器(Container): 容器就是包含其它對象的對象。
E: 管道:以前對管道的理解是兩個進程通過管道來進行通信,比如在IIS5中,inetinfo.exe通過“命名管道”將請求交給aspnet_wp.exe(之所以稱為命名管道,是因為給這個管道起了一個隨機的名字)?,F在又出來了一個http 管道(http pipeline),但是這回卻是在同一個進程(比如IIS6.0中w3wp.exe)里面,這是怎么回事?讓我們來看看“管道”的本質,我們分析一下實際生活中的管道,我們看到管道具有下面兩個特征:
a 從里面流過的東西來看:東西從管道一頭進入,從另外一頭出來,東西還是原來的東西。
b 管道從外部形態來看:它連通了兩個不同的地方,也就是說它代表著一種流向,一種流程,一種順序。
是的,我們計算機中的術語和生活中的概念是相通的。我們這里說的HTTP管道,就是指Http Module,Http Handler這些對象。而在這些HTTP管道流過的東西是同一個對象,那就是Http Context對象。在Http Module,Http Handler這些對象中對Http Context對象的處理,不過是對Http Context對象中的內容進行改變(最大的改變就是給Response對象賦上內容),但是沒有改變它的結構。
2 幾個容易造成誤解的概念:
A:Http Application和我們在頁面中使用的Application對象:這兩者是不同的。前者代表著我們整個應用程序,對于我們的每個請求,HttpApplicationFactory都會分配一個Http Application對象,這個對象將管理著這個對請求的處理邏輯,或者說它是事件調度中心,你可以看到我們的Global.asax實際上就繼承了HttpApplication。我們在頁面中使用的Application是一個狀態的概念,它是HttpApplicationState的一個實例,并且是“嵌”在httpContext對象上的一個子對象。
B:.NET運行時和HTTP運行時:NET運行時即是CLR,它的核心是MsCorEE.dll。后者是HTTP RunTime,它是System.web中httpRuntime類的實例。HttpRuntime負責Http Application, Http Context的創建和初始化等工作。這兩者是不同的。
C: Http Application, Http Context, Http Module,Http Handler
對于每個請求都被路由到一個HttpApplication對象上.HttpApplicationFactory類根據應用程序的負載為你的ASP.NET應用創建一個HttpApplication對象池并為每個請求分發HttpApplication對象的引用.
這里我再次強調,HttpApplication的主要職責是作為Http管道的事件控制器,httpApplication它本身對發送給應用程序的數據一無所知-它只是一個通過事件來通訊的消息對象.它觸發事件并通過HttpContext對象來向被調用函數傳遞消息.實際的當前請求的狀態數據由HttpContext對象維護。你可以用Reflector看一看HttpContext類,里面包含著Request,Response,Application,Server,Session等表示狀態的對象。其實,HttpContext本身也表示一種狀態,它還有兩個很重要的屬性,Current和Items,前者用來代表自己,后者是可以存儲任何對象的集合,你不要小看后者,它真的非常有用。鑒于自己與Context曾經有過一段情史,我將在以后寫篇blog詳細介紹它。
httpModule,有人說是它是“監視器”,有人說是“過濾器”,他們都是從不同角度來看httpModule,所以都是對的。httpModule提供了對請求進入http Handler處理之前的預處理和經過http handler處理后的事后處理,既然可以預處理,當然可以實現攔截請求,不交給http handler去處理,實現“過濾”的功能。從另外一個角度上來說,一旦有請求到來,便會初始化httpModule(httpApplication中有負責初始化httpModule的InitModules()方法),當然也就意味著httpModule監視著請求(也就是“監視器”的來源),畢竟它是我們能夠對請求進行處理的開始。需要說明一點的是,ASP.NET只是為我們提供了這個能力,你需要自己去添加事件代碼來實現控制,比如你可以在Global.asax中的事件處理函數中添加代碼,你也可以自己定義http module.在附件4《asp-net framework深度歷險.pdf》你可以看到具體的實例。至于http Handler,我們的頁面其實就是一個http Handler,你可以從System.Web.UI.Page類(我們所有頁面的基類)的聲明中看到它要實現IHttpHandler接口。你可以翻閱《.NET程序設計技術內幕》這本書的8.5《圖形控件》看看自己定制實現http Handler的好處。
但是,我不同意在附件4《asp-net framework深度歷險.pdf》中所說,認為請求是一個單線流式的經過Http ApplicationFactory->Http Application-> Http Module -> Http Handler ->…。從附件1《[翻譯]了解ASP.NET底層架構.doc》的圖6也可以看到,所有的處理起點是在最左邊的ASP.NET開始,為什么呢?實際上Http Module和Http Handler都是“嵌”在Http
Application上的,整個流程是由http Application進行調度的。從另外一個角度上來說,http Application的大部分功能都是由Http Module來實現的,這些Http Module實際上就是在http Application啟動并參與處理請求時被實例化的類,你可以在web.config中ttp Module> 看到預定義的http Module, 包括會話,驗證等。
最后,預祝你也能“抱得美人歸”。
原文轉自:http://www.anti-gravitydesign.com