MVC之前-ASP.NET初始化流程分析1

來源:互聯網
上載者:User

標籤:mvc   失敗   工作模式   自身   http請求   conf   public   ppi   ret   

Asp.net Mvc是當前使用比較多的web架構,也是比較先進的架構。我打算根據自己的實際項目經驗以及相關的源碼和一些使用Asp.net Mvc的優秀項目(主要是orchard)來說一說自己對於Asp.net Mvc原理的理解和一些實踐經驗。目前.net的大部分源碼都已經開放,這大大方便了我們對Asp.net Mvc的分析,下面就從Http請求進入Mvc架構處理之前的基本流程說起。

由於各IIS版本和工作模式(傳統模式、整合模式)的不同,Http請求進入Asp.net的處理通道並不一樣,這裡不去細究裡面的細節,就從建立應用程式定義域開始:

AppManagerAppDomainFactory分析

註:AppDomainFactory及AppManagerAppDomainFactory類在System.Web.Hosting中實現

在建立Appdomain時會調用IAppDomainFactory介面,該介面的實現如下:

 public sealed class AppDomainFactory : IAppDomainFactory {        private AppManagerAppDomainFactory _realFactory;        public AppDomainFactory() {            _realFactory = new AppManagerAppDomainFactory();        }        public Object Create(String module, String typeName, String appId, String appPath,String strUrlOfAppOrigin, int iZone) {            return _realFactory.Create(appId, appPath);        }}

該實現會調用AppManagerAppDomainFactory完成實際的建立過程。

  public sealed class AppManagerAppDomainFactory : IAppManagerAppDomainFactory {        private ApplicationManager _appManager;        public AppManagerAppDomainFactory() {            _appManager = ApplicationManager.GetApplicationManager();            _appManager.Open();        }        public Object Create(String appId, String appPath) {            try {                if (appPath[0] == ‘.‘) {                    System.IO.FileInfo file = new System.IO.FileInfo(appPath);                    appPath = file.FullName;                }                if (!StringUtil.StringEndsWith(appPath, ‘\\‘)) {                    appPath = appPath + "\\";                }                ISAPIRuntime isapiRuntime = (ISAPIRuntime)_appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost,false, null);                isapiRuntime.StartProcessing();                return new ObjectHandle(isapiRuntime);            }            catch (Exception e) {                Debug.Trace("internal", "AppDomainFactory::Create failed with " + e.GetType().FullName + ": " + e.Message + "\r\n" + e.StackTrace);                throw;            }        }  }

代碼的主要作用,就是通過ApplicationManager的CreateObjectInternal建立AppDomain,建立HostingEnvironment等,最終擷取ISAPIRuntime的執行個體,然後讓Unmanaged 程式碼調用。

ApplicationManager分析

註:ApplicationManager類在System.Web.Hosting中實現

首先看ApplicationManager類中的靜態建立ApplicationManager對象的方法:

public static ApplicationManager GetApplicationManager() {        if (_theAppManager == null) {            lock (_applicationManagerStaticLock) {                if (_theAppManager == null) {                    if (HostingEnvironment.IsHosted)                        _theAppManager = HostingEnvironment.GetApplicationManager();                    if (_theAppManager == null)                        _theAppManager = new ApplicationManager();                }            }        }        return _theAppManager;}

如果HostingEnvironment已經建立則可以直接返回當前HostingEnvironment設定的ApplicationManager,如果沒有則建立新的ApplicationManager執行個體。

然後看ApplicationManager的CreateObjectInternal方法:

internal IRegisteredObject CreateObjectInternal(String appId, Type type, IApplicationHost appHost, bool failIfExists, HostingEnvironmentParameters hostingParameters) {        if (!typeof(IRegisteredObject).IsAssignableFrom(type))            throw new ArgumentException(SR.GetString(SR.Not_IRegisteredObject, type.FullName), "type");        HostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters);        ObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);        return (h != null) ? h.Unwrap() as IRegisteredObject : null;    }

首先要先取得HostingEnvironment的執行個體,然後通過該執行個體的CreateWellKnownObjectInstance方法返回上述Create方法需要的ISAPIRuntime的執行個體。先來看如何擷取HostingEnvironment執行個體的方法GetAppDomainWithHostingEnvironment。

private HostingEnvironment GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) {        LockableAppDomainContext ac = GetLockableAppDomainContext (appId);        lock (ac) {            HostingEnvironment env = ac.HostEnv;            if (env != null) {                try {                    env.IsUnloaded();                }                catch(AppDomainUnloadedException) {                    env = null;                }            }            if (env == null) {                env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters);                ac.HostEnv = env;                Interlocked.Increment(ref _accessibleHostingEnvCount);            }            return env;        }    }

首先會檢查字典是否會有已經存在的HostingEnvironment執行個體,如果有就返回,沒有就會建立一個新的並儲存到字典中,查看相關代碼發現最終會調用ApplicationManager的私人方法CreateAppDomainWithHostingEnvironment建立AppDomain和HostingEnvironment。

  private HostingEnvironment CreateAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters)  {       ……       appDomain = AppDomain.CreateDomain(domainId,GetDefaultDomainIdentity(),setup);       ……       Type hostType = typeof(HostingEnvironment);       String module = hostType.Module.Assembly.FullName;       String typeName = hostType.FullName;       ObjectHandle h = null;       ……       try {           h = Activator.CreateInstance(appDomain, module, typeName);       }       ……       HostingEnvironment env = (h != null) ? h.Unwrap() as HostingEnvironment : null;       if (env == null)           throw new SystemException(SR.GetString(SR.Cannot_create_HostEnv));       IConfigMapPathFactory configMapPathFactory = appHost.GetConfigMapPathFactory();       if (appDomainStartupConfigurationException == null) {           env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel);       }       else {           env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel, appDomainStartupConfigurationException);       }       return env;}

可以看到代碼建立了AppDomain和HostingEnvironment執行個體,建立HostingEnvironment執行個體以後,緊接著會調用其Initialize方法來進行初始化,然後返回對象執行個體。

HostingEnvironment分析

Initialize初始化方法,注意該方法的第一個參數是this,也就是ApplicationManager執行個體自身,這樣會在HostingEnvironment中設定ApplicationManager,因而初始化之後可以通過HostingEnvironment擷取ApplicationManager 。Initialize方法調用HttpRuntime的靜態方法,進行一些初始化工作(其中會調用BuildManager的InitializeBuildManager方法進行初始化另外一些工作,其中包括編譯App_Code目錄下所有的.NET原始碼)。最後如果HostingEnvironment初始化失敗時會設定hostingInitFailed為true。

internal void Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException){    ……    _appManager = appManager;    ……    HttpRuntime.InitializeHostingFeatures(hostingFlags,policyLevel,appDomainCreationException);    ……    catch (Exception e) {        _hostingInitFailed = true;    }}

建立HostingEnvironment後,會調用其方法CreateWellKnownObjectInstance建立ISAPIRuntime。建立好ISAPIRuntime執行個體後初始化工作就完成了第一個階段,整個過程如所示:

MVC之前-ASP.NET初始化流程分析1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.