繼續上一章節的內容,通過HttpApplicationFactory的GetApplicationInstance靜態方法獲取實例,然後執行該實例的BeginProcessRequest方法進行執行余下的Http Pipeline 操作,代碼如下:
// Get application instance
IHttpHandler app = HttpApplicationFactory.GetApplicationInstance(context);
那GetApplicationInstance這個方法究竟做了啥呢?難道只是new一個新對象出來?感覺應該不像,那我們就來看看HttpApplicationFactory類的GetApplicationInstance靜態方法源碼:
internal static IHttpHandler GetApplicationInstance(HttpContext context) {
if (_customApplication != null)
return _customApplication;
// Check to see if it's a debug auto-attach request
if (context.Request.IsDebuggingRequest)
return new HttpDebugHandler();
_theApplicationFactory.EnsureInited();
_theApplicationFactory.EnsureAppStartCalled(context);
return _theApplicationFactory.GetNormalApplicationInstance(context);
}
裡面有3行代碼我已經標記為粗體了,在解釋每行代碼的具體作用之前,先看看_theApplicationFactory對象實例從哪裡來,通過查看該字段的聲明代碼可以看到它是單例的實現。
// the only instance of application factory private static HttpApplicationFactory _theApplicationFactory = new HttpApplicationFactory();
第一行粗體代碼是執行,該實例的EnsureInited方法,這個方法會通過lock的方式調用Init方法(好處自然不用多說了吧),代碼如下:
private void EnsureInited() {
if (!_inited) {
lock (this) {
if (!_inited) {
Init();
_inited = true;
}
}
}
}
通過查找 Init方法的代碼以及其中2行如下代碼裡的細節,我們可以得知,這2行代碼主要是從global.asax獲取內容,然後進行編譯。
_appFilename = GetApplicationFile();
CompileApplication();
所以,HttpApplicationFactory._theApplicationFactory.EnsureInited() 的方法首先檢查HttpApplicationFactory是否被初始化,如果沒有,就通過HttpApplicationFactory.Init()進行初始化。在Init()中,先獲取global.asax文件的完整路徑,然後調用CompileApplication()對global.asax進行編譯。
第2行粗體的EnsureAppStartCalled方法,最終會調用如下的私有方法FireApplicationOnStart,代碼如下:
private void FireApplicationOnStart(HttpContext context) {
if (_onStartMethod != null) {
HttpApplication app = GetSpecialApplicationInstance();
app.ProcessSpecialRequest(
context,
_onStartMethod,
_onStartParamCount,
this,
EventArgs.Empty,
null);
RecycleSpecialApplicationInstance(app);
}
}
通過代碼我們能夠得知 HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context) 創建特定的HttpApplication實例,觸發ApplicationOnStart事件,執行ASP.global_asax中的 Application_Start(object sender, EventArgs e)方法。然後在處理完事件以後就立即被回收掉,因為系統初始化只需要一次,但是其中的GetSpecialApplicationInstance裡會對IIS7做一些特殊的事情,我們後面的章節會講到。
第3行的粗體代碼是我們這裡要說的重點,它方法裡的代碼如下:
private HttpApplication GetNormalApplicationInstance(HttpContext context) {
HttpApplication app = null;
lock (_freeList) {
if (_numFreeAppInstances > 0) {
app = (HttpApplication)_freeList.Pop();
_numFreeAppInstances--;
if (_numFreeAppInstances < _minFreeAppInstances) {
_minFreeAppInstances = _numFreeAppInstances;
}
}
}
if (app == null) {
// If ran out of instances, create a new one
app = (HttpApplication)HttpRuntime.CreateNonPublicInstance(_theApplicationType);
using (new ApplicationImpersonationContext()) {
app.InitInternal(context, _state, _eventHandlerMethods);
}
}
return app;
}
本欄目