首页 > 代码库 > MVC之前-ASP.NET初始化流程分析1

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

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的实例,然后让非托管代码调用。

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