概述
分析一个的ASP.NET项目源码,首先可以浏览其项目结构,大致一窥项目其全貌,了解项目之间的依赖关系。其次可以浏览Web.configGlobal.asax文件,找到应用程序的入口点。
本 文主要分析Orchard项目的Global.asax文件,而真正的分析入口点在Global.asax的CodeBehind文件 Global.asax.cs中,即Orchard.Web.MvcApplication类(以下简称MvcApplication类)。

 
MvcApplication类处理了三个事件Start,BeginRequest和EndRequest。其中是否真有名为"Start"的事件还不明确,这里暂且这么简单的理解。
根 据约定,这三个事件分别对应Application_Start、Application_BeginRequest和 Application_EndRequest事件处理程序(方法),当然也可以通过重写HttpApplication的Init方法注册其他名称的事 件处理程序——Application_Start除外。
 
Start是个特殊事件,仅在请求 ASP.NET 应用程序中第一个资源(如aspx页)时调用。在该事件的处理程序(Application_Start方法)中,可用于也应该仅用于在应用程序启动期间设置静态共享数据。Orchard中主要用于配置Autofac容器、安装扩展(Modules和Themes统称为扩展)、创建并激活Shell(子站点)。

BeginRequest事件在 ASP.NET 响应请求时作为 HTTP 执行管线链(管道)中的第一个事件发生。Orchard中主要用户监视扩展;如果扩展发生改变会重新安装扩展、重新创建并激活Shell;如果Shell状态等也发生改变会重新激活Shell。

EndRequest事件在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生。Orchard中主要用于处理完"处理引擎(ProcessingEngine)"中的任务(Task)。
 
一、Application_Start方法
下面的代码分析要在MvcApplication类和Orchard.WarmupStarter.Starter<T>类(以下简称Starter<T>类)之间切换。
Application_Start方法首先调用了RegisterRoutes方法,添加了一个路由配置,将对后缀为".axd"的请求排除在ASP.NET MVC处理管道之外。这里将方法内联后看:
    RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}" );
接着Application_Start方法中使用泛型类型参数IOrchardHost,调用Starter<T>类带三个委托参数的构造函数创建其实例并赋给了静态私有字段_starter:
    _starter = new Starter<IOrchardHost >(HostInitialization, HostBeginRequest, HostEndRequest);
其中静态私有字段_starter定义在MvcApplication类中有定义:
    private static Starter< IOrchardHost> _starter;
另暂且不管IOrchardHost的定义及其作用,这里只需要知道Starter<T>类有责任创建一个IOrchardHost(DefaultOrchardHost)实例。
Starter<T> 类构造函数接受三个委托参数。在创建该类型的对象时,传入HstInitialization、HostBeginRequest和 HostEndRequest的三个参数是在MvcApplication类中定义的三个私有静态方法(当然,会被包装成委托):
    IOrchardHost HostInitialization(HttpApplication application)
    void HostBeginRequest(HttpApplication application, IOrchardHost host)
    void HostEndRequest(HttpApplication application, IOrchardHost host)
 

下面转入Starter<T>类看其构造函数的定义:

         public Starter(Func <HttpApplication, T> initialization, Action<HttpApplication , T> beginRequest, Action<HttpApplication , T> endRequest) {
            _initialization = initialization;
            _beginRequest = beginRequest;
            _endRequest = endRequest;
            }
 
可见该构造函数内部只是简单的赋值操作,将参数值赋给Starter<T>类内部对应的私有的委托类型字段。
 
再转回Application_Start方法继续分析。
Application_Start方法接着调用_starter的OnApplicationStart方法,将当前的MvcHttpApplication实例作为参数传入:

_starter.OnApplicationStart( this);

深 入Starter<T>.OnApplicationStart方法内部,该方法通过线程池启动一个线程。新线程中最终会调用 MvcHttpApplication类中的HostInitialization方法——即作为参数传给Starter<T>构造函数的委 托所包装的方法。具体分析请参考下一篇关于Orchard.WarmupStarter程序集的分析。这里再看看HostInitialization方 法的定义:      
    private static IOrchardHost HostInitialization( HttpApplication application) {
        var host = OrchardStarter .CreateHost(MvcSingletons);
 
        host.Initialize();
 
        // initialize shells to speed up the first dynamic query
        host.BeginRequest();
        host.EndRequest();
 
         return host;
    }
该方法目的是创建一个IOrchardHost(DefaultOrchardHost)对象并调用其几个方法,然后将其返回。这里暂不深究IOrchardHost这几个方法的作用。
 
二、Application_BeginRequest方法和Application_EndRequest方法
这两个方法比较简单,只是简单调用Starter<T>类的对应方法:

     protected void Application_BeginRequest() {
        _starter.OnBeginRequest( this);
    }
 
    protected void Application_EndRequest() {
        _starter.OnEndRequest( this);
    }
 
Starter<T>的OnBeginRequest和OnEndRequest方法会调用MvcApplication的HostBeginRequest和HostEndRequest方法:
    public void OnBeginRequest(HttpApplication application)
    {
        // ... (省略的代码请查看Starter<T>类,在下一篇中将会进行分析)
        // Only notify if the initialization has successfully completed
        if (_initializationResult != null )
        {
            _beginRequest(application, _initializationResult);
        }
    }
 
    public void OnEndRequest(HttpApplication application)
    {
        // Only notify if the initialization has successfully completed
        if (_initializationResult != null )
        {
            _endRequest(application, _initializationResult);
        }
    }
HostBeginRequest和HostEndRequest方法最终会转到对IOrchardHost(DefaultOrchardHost)对应方法的调用:

    private static void HostBeginRequest( HttpApplication application, IOrchardHost host) {
        application.Context.Items[ "originalHttpContext"] = application.Context;
        host.BeginRequest();
    }
 
    private static void HostEndRequest( HttpApplication application, IOrchardHost host) {
        host.EndRequest();
    }
注意,HostBeginRequest方法将当前请求上下文(HttpContext)保存在会话状态(HttpContext.Items)中。
 
从 上面不难看出,一项交由MvcApplication来完成的工作,它推给了Starter<T>,后者完成一部分后又转给 MvcApplication处理,MvcApplication接着处理一部分后,把剩下的工作全交给 IOrchardHost(DefaultOrchardHost)来完成。
 
在分析Orchard.WarmupStarter程序集的时候将详细分析Starter<T>类。对IOrchardHost(DefaultOrchardHost)也有专门的篇幅来分析。
三、疑问 对MvcHttpApplication分析暂时就到这里,它虽然就短短60多行代码,而且包括注释。但留给我们的疑问倒却不少:
1、上面虽然数次提到IOrchardHost(DefaultOrchardHost),但它到底是什么,它的作用又是什么?

2、MvcApplication.HostInitialization方法中,调用OrchardStarter.CreateHost方法创建IOrchardHost实例的,它是如何创建的?

3、MvcApplication.HostInitialization方法中,调用IOrchardHost.Initialize方法后,为什么还要调用IOrchardHost.BeginRequest和IOrchardHost.EndRequest方法?
4、为什么要在MvcApplication.HostBeginRequest方法中将当前请求上下文(HttpContext)保存在会话状态(HttpContext.Items)中? 5、Orchard.WarmupStarter程序集是做什么用的? 6、Starter<T>在把任务传回MvcApplication之前,完成了那些工作? 7、MvcApplication.MvcSingletons方法涉及到IoC/DI,Autofac是如何工作的?
相关类型: Orchard.WarmupStarter.Starter<T>
Orchard.Environment.DefaultOrchardHost : Orchard.Environment.IOrchartHost
Orchard.Environment.OrchardStarter
 
参考资料:

HttpApplication的认识与加深理解

Orchard源码分析(2):Orchard.Web.MvcApplication类(Global)的更多相关文章

  1. Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)

    概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplicat ...

  2. JUC源码分析-集合篇:并发类容器介绍

    JUC源码分析-集合篇:并发类容器介绍 同步类容器是 线程安全 的,如 Vector.HashTable 等容器的同步功能都是由 Collections.synchronizedMap 等工厂方法去创 ...

  3. 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)

    [1]前言 本篇幅是对 线程池底层原理详解与源码分析  的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...

  4. Orchard源码分析(1):Orchard架构

      本文主要参考官方文档"How Orchard works"以及Orchardch上的翻译.   源码分析应该做到庖丁解牛,而不是以管窥豹或瞎子摸象.所以先对Orchard架构有 ...

  5. Spring Boot 2.x 启动全过程源码分析(上)入口类剖析

    Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boot 为什么这么简便的奥秘. 本篇基于 Spring Boot 2.0.3 版本进 ...

  6. spring源码分析系列 (8) FactoryBean工厂类机制

    更多文章点击--spring源码分析系列 1.FactoryBean设计目的以及使用 2.FactoryBean工厂类机制运行机制分析 1.FactoryBean设计目的以及使用 FactoryBea ...

  7. Orchard源码分析(3):Orchard.WarmupStarter程序集

    概述 Orchard.WarmupStarter程序集包含三个类:WarmupUtility.WarmupHttpModule和Starter<T>.该程序集主要为Orchard应用启动初 ...

  8. Orchard源码分析(7.1):Routing(路由)相关

    概述 关于ASP.NET MVC中路由有两个基本核心作用,一是通过Http请求中的Url参数等信息获取路由数据(RouteData),路由数据包含了area.controller.action的名称等 ...

  9. Orchard源码分析(5.1):Host初始化(DefaultOrchardHost.Initialize方法)

    概述 Orchard作为一个可扩展的CMS系统,是由一系列的模块(Modules)或主题(Themes)组成,这些模块或主题统称为扩展(Extensions).在初始化或运行时需要对扩展进行安装:De ...

随机推荐

  1. dede使用方法----如何自定义字段

    我们在用dede做东西的时候,有时候需要添加一些dede里面没有的字段,有dede后台里面可以添加相关的自段,下面我就以如何给产品添加一个价格的字段来讲述一下如何给dede添加字段,并且调用它. 1. ...

  2. 系统间通信(3)——IO通信模型和JAVA实践 上篇

    来源:http://blog.csdn.net/yinwenjie 1.全文提要 系统间通信本来是一个很大的概念,我们首先重通信模型开始讲解.在理解了四种通信模型的工作特点和区别后,对于我们后文介绍搭 ...

  3. Python 编辑器 tips

    1.  IDLE界面美化 注意IDLE是可以设置语法高亮的:(美化参考 http://www.linuxidc.com/Linux/2012-07/66129.htm) windows 用户,直接打开 ...

  4. MapReduce基础知识

    hadoop版本:1.1.2 一.Mapper类的结构 Mapper类是Job.setInputFormatClass()方法的默认值,Mapper类将输入的键值对原封不动地输出. org.apach ...

  5. HA模式下历史服务器配置

    笔者的集群是 HA 模式的( HDFS 和 ResourceManager HA).在 ” Hadoop-2.5.0-cdh5.3.2 HA 安装" 中详细讲解了关于 HA 模式的搭建,这里就不再赘述 ...

  6. 开个帖,开始学习shell编程

    恩,就这么开始了 首先说一下这个小小的插曲...写着写着,它就崩溃了,然后我也崩溃了...崩溃的我到处找一个不会让我崩溃的工具,然后找来找去就找到了scribefire. 1. 关于从Command ...

  7. AngularJs $sce 和 $sceDelegate 上下文转义

    $sce $sce 服务是AngularJs提供的一种严格上下文转义服务. 严格的上下文转义服务 严格的上下文转义(SCE)是一种需要在一定的语境中导致AngularJS绑定值被标记为安全使用语境的模 ...

  8. FZU 1894 志愿者选拔(单调队列)

    传送门 Description 世博会马上就要开幕了,福州大学组织了一次志愿者选拔活动.参加志愿者选拔的同学们排队接受面试官们的面试.参加面试的同学们按照先来先面试并且先结束的原则接受面试官们的考查. ...

  9. runtime笔记一

    一.iOS中_cmd The _cmd variable is a hidden argument passed to every method that is the current selecto ...

  10. Javascript 与正则表达式

    一.正则表达式(regular expression简称res) 二.元字符及其在正则表达式上下文中的行为 三.正则表达式的常用方法 四.与正则表达式有关的字符串对象的方法 五.常用的正则表达式的操作 ...