Agenda
- 前言:
- HttpApplication物件
- 取得使用 HttpApplication物件 (GetApplicationInstance)
- 返回一個 HttpApplication 物件 (GetNormalApplicationInstance)
- 小結
前言:
附上Asp.net執行請求流程圖.

在前一篇我們說到HttpRunTime會透過GetApplicationInstance來取得一個IHttpHandler對象.
今天跟著原始碼來了解到底回傳一個什麼IHttpHandler物件給HttpRunTime使用.
查看原始碼好站 Reference Source
HttpApplication物件
HttpApplication是整個ASP.NET基礎的核心。一個HttpApplication物件在某個時刻只能處理一個請求,只有完成對某個請求處理後,該HttpApplication才能用於後續的請求的處理。
所以ASP.NET利用物件程序池機制來建立或者取得HttpApplication物件。具體來講,當第一個Http請求抵達的時候,ASP.NET會一次建立多個HttpApplication物件,並將其置於池中,選擇其中一個物件來處理該請求。
而如果程序池中沒有HttpApplication物件,Asp.net會建立新的HttpApplication物件處理請求
HttpApplication物件處理Http請求整個生命週期是一個相對複雜的過程,在該過程的不同階段會觸發相應的事件。我們可以註冊相應的事件(如同上一篇介紹事件表)
下圖就是模擬HttpApplication的ObjectPool樣子

取得使用 HttpApplication物件 (GetApplicationInstance)
讓我們看看GetApplicationInstan方法做了什麼事情.
1 | private static HttpApplicationFactory _theApplicationFactory = new HttpApplicationFactory(); |
_theApplicationFactory是一個靜態物件
_theApplicationFactory呼叫三個方法EnsureInited,EnsureAppStartCalled,GetNormalApplicationInstance,讓我們一一來解析做了些什麼事情吧
HttpApplicationFactory 初始化 (EnsureInited方法)
通過查找Init方法的代碼以及其中2行如下代碼裡的細節,我們可以得知,這2行代碼主要是從global.asax獲取內容,然後進行編譯。
HttpApplicationFactory.EnsureInited()方法檢查HttpApplicationFactory是否已經被初始化,如果沒有就呼叫HttpApplicationFactory.Init()進行初始化。
在Init()中,先獲取網站下global.asax文件完整路徑(透過GetApplicationFile方法),最後呼叫CompileApplication()方法對global.asax進行編譯.
在EnsureInited方法
1 | private void EnsureInited() { |
ReflectOnApplicationType方法取得目前特別事件方法,並添加到相對應的MethodInfo成員上
會透過以下三類方法名稱去取方法資訊
Application_OnStartorApplication_StartApplication_OnEndorApplication_EndSession_OnEndorSession_End
取得這些資訊會提供
EnsureAppStartCalled去呼叫Application_OnStart方法
1 | private void ReflectOnApplicationType() { |
Application_Start方法為什麼只會呼叫一次? (EnsureAppStartCalled)
HttpApplicationFactory.EnsureAppStartCalled方法建立一個HttpApplication物件並觸發Application_OnStart事件(執行Global.asax中的Application_Start(object sender, EventArgs e))
在處理完事件Application_OnStart後HttpApplication物件會立即被回收掉,因為系統初始化只需要一次
但是其中
GetSpecialApplicationInstance裡會對IIS7做一些特殊的事情這裡就不多提
1 | private void EnsureAppStartCalled(HttpContext context) { |
在處理完事件
Application_OnStart呼叫RecycleSpecialApplicationInstance回收HttpApplication物件
返回一個 HttpApplication 物件 (GetNormalApplicationInstance)
方法中主要做.
- 判斷
_freeList集合中是否有可用HttpApplication物件(物件程序池中),如果沒有就利用HttpRuntime.CreateNonPublicInstance(_theApplicationType)透過反射建立一個新的HttpApplication返回(呼叫完IHttpHandler.ProcessRequst方法後會將這個物件存入_freeList中),最後將
1 | private HttpApplication GetNormalApplicationInstance(HttpContext context) { |
所以最終我們是返回一個HttpApplication物件來使用.
小結
今天我們學到
IHttpHandler GetApplicationInstance(HttpContext context)其實是返回一個HttpApplication物件.- 在
EnsureAppStartCalled方法中呼叫FireApplicationOnStart方法動態建立一個HttpApplication物件,呼叫完Application_OnStart事件就回收掉並使用一個flag布林值代表已經呼叫過. - 這個工廠會有一個
_freeList集合來存取之前用過的HttpApplication物件,如果集合中沒有適合的HttpApplication物件就會使用反射返回一個新的HttpApplication並將他初始化. - 所以
HttpRuntime呼叫的是HttpApplication物件的ProcessRequest方法
下篇會跟大家介紹HttpApplication類別成員詳細資訊
__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/Ithelp-day4/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!