程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> MVC系列(4) Http Pipeline詳細分析(上)

MVC系列(4) Http Pipeline詳細分析(上)

編輯:關於ASP.NET

繼續上一章節的內容,通過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;   
}

本欄目

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved