zoukankan      html  css  js  c++  java
  • 上一篇随笔<深入剖析ASP.NET组件设计>一书中第三章关于ASP.NET运行原理的补白

    上一篇随笔<深入剖析ASP.NET组件设计>一书中第三章关于ASP.NET运行原理的补白总览了大体的结构及流程,看完后,相信,可以对整体的流程有所了解.但是,许多细节的问题,例如像HttpRuntime如何建立HttpApplication对象等问题,仍然没有解说清楚
    当然,了解这些细节并不是必需的,就算你不知道HttpApplication对象是如何被创建的,你仍能够创建出好的组件.但是,如果你仔佃研究这些细节,相信你会吸收不少技术养分.例如,通过本文讲述的HttpApplication对象的创建过程,你就可以深切的体会到ASP.NET设计的精妙之处,并且,你可以学到Factory设计模式的运用,这也是黄先生这本书的另一个特点,就是,他不光讲述了ASP.NET的一些东西,同时教你一些编程的方法和技巧,对于一些学习设计模式,而又觉得难以理解设计模式的初学者来说,通过阅读黄先生的这本书,能够让你看到不少设计模式实地运用的讲解.

    实际上HttpApplication并不是HttpRuntime所创建的.HttpRuntime只是向HttpApplicationFactory提出请求,要求返回一个HttpApplication对象.HttpApplicationFactory在接收到请求后,会先检查是否有已经存在并空闲(可以这样讲吗?比较形象一点)的HttpApplication对象,如果有,则从池中取出一个HttpApplication对象返回给HttpRuntime,如果没有的话,则要创建一个HttpApplication对象给HttpRunTime(英文叫Pooling,好比你养鱼一样,每个鱼是一个HttpApplication,而你就是HttpApplicationFactory,别人问你要鱼,你就会检查池中有没有现成的,并且是合适的鱼,有的话,捞一个给别人,没有的话,创造一条鱼,放入池中,再给别人,听起来不错,你好像威力无比哟)

    实际上,我们再将HttpApplication的创建过程放大来看的话,还有不少细节.上面讲述的是HttpApplication是如何被请求以及如何被返回给HttpRunTime的,概括的来说,就是HttpRunTime不直接建立HttpApplication,而是把创建的权利交给HttpApplicationFactory,这里实际上运用的正是Factory模式,而且不是一般的Factory模式,而是带有Pool能力的Factory模式.HttpFactory对象负责建立并缓存HttpApplication对象同时返回合适的对象给HttpRuntime.这里就有一个问题了,也就是说,同一时刻,HttpApplicationFactory的"养鱼池"里可能有很多个HttpApplication对象.那最多他能够同时缓存多少个HttpApplication对象呢?默认情况下,HttpApplication对象的最大缓存数目为100,并且HttpApplicationFactory会循环释放超过此数量的HttpApplication对象(那是不是意味着超出100个人同时访问的系统,无论设计的再好,也会因此而遭遇到性能瓶颈呢?)

    HttpApplicationFactory创建HttpRuntime的过程是一个Parse与Compile的过程.原书中黄先生说,HttpApplicationFactory会运用Parser对象来解析Global.asax,同时,加载Global.dll文件,同时,创建一个继承自此类的源代码,最后运用Compiler对象来编译源代码,再创建一个HttpApplication对象.这一点,也可以从黄先生书中配图可以看到.但是,估计许多人看到这里已经晕了.你可以这样理解这个过程:

    首先,黄先生所言的Parser与Compiler对象其实是指Codeparser与CodeCompiler类的两个实例,它们是.net类库的一部分,Codeparser对象的作用是将一段文本转换为一段C#或VB源代码
    (
    看不懂吗?有没有想过,你在ASPX页面中用<ASP:Label runat=server></ASP:Label>中定义的ASP.NET控件在运行时究竟变成什么东东呢?Parser对象可以负责将<asp:Label>以及类似的控件以及<script runat="server">中的代码解析成对应的C#源码片断,也就是 Label label2=new Label();的形式,它返回一个CodeCompileUnit对象.
    如果你仍然不理解ASP.NET的这种Parser行为的话,你就不了解ASP.NET控件的运作形式.你必须深刻的记住一点,那就是,处理对应的ASP.NET页面请求的不是ASP.NET也不是IIS,更不是ASP.NET页面本身.而是ASP.NET运用PARSER对象将控件标记转换成C#源码并且派生于PAGE类,被编译并实例外的一个对象.这一点非常重要,跟ASP不同,我们知道ASP的代码是被加载到内存并且被ASP运行时解析然后返回HTML的,但是,ASP.NET不是,ASP.NET处理页面请求的是一个类的实例,它是一个可以输出HTML的对象.同样的,在HttpApplication对象的创建过程中,也是运用了Parser,因为HttpApplication实际上要依赖于Global.ASAX文件,而这个文件,我们知道,如果不用CodeBehind来写的话,它就是一个<Script Runat="Server">,换句话来说,它也是一段标记,这段标记必须被转换成C#源代码,然后编译成一个类,再产生这个类的实例,这个类就是HttpApplication.实际上,像CodeParser,CodeCompiler以及Reflection等构成的CodeDom技术是.NET核心部分之一,.NET的运行非常依赖于这些部分
    )

    至于parser为什么要解析Global.ASAX同地又要加载Assembly,这一点上,许多人会想不通.因为如果使用CODEBehind技术的话,所有代码已经包含在Assembly中了呀,为什么还要解析Global.ASAX呢?如果你这样想,你就错了,首先,也可能Global.ASAX中定义了一部分函数,而Assembly中定义了另一部分,其次,没有人说Gloabal.ASAX中只允许包含代码呀,也有人喜欢在其中利用OBJECT标记来定义APPLICATION范围或者Session范围的对象呀,因此,parser有必要解析Global.ASAX文件,将其转换为C#代码片断,然后,加载Assembly,利用Reflection技术创建一个继承自类Global(默认情况下的类名)的新类的源代码,然后将两部分的源代码合并(Ghost Application Class Source),运用Compiler创建出一个新类(Ghost Application Class Assembly),并且生成新类的一个实例来返回给HttpRuntime.

    原书中,黄先生说Parser会加载Global.dll文件,我想,这可能是笔误,很多人不明白Global.dll究竟是什么.写过ASP.NET的人更知道,根本没有这个文件.我想,Global.dll就是包含global.asax文件的工程编译产生的Assembly,由于此Assembly包含了CodeBehind方式下的Global类的信息.因此,Parser才需要加载它

    至此,HttpApplication对象创建完毕了.另外,就AppDomain,HttpRuntime,HttpContext,HttpSession,HttpApplication,HttpModule这些对象的数量以及与用户数量的对应关系做以下描述
    每一个ASP.NET只有一个AppDomain,每一个AppDomain对应一个httpRunTime,它们都与用户数量无关
    每一个用户对应一个HttpApplication,一个HttpSession,一个HttpContext和一组HttpModule

    如果对于HttpApplication对象生成过程中的Parser与Compiler不清楚的话(这部分很重要,包括AspX页面的处理方法也是类似的),下面的图或许有助理解:
  • 相关阅读:
    Oracle SQL语句收集
    SqlParameter In 查询
    SQL 性能优化
    Entity Framework
    【XLL API 函数】 xlfSetName
    【XLL API 函数】xlfUnregister (Form 2)
    【XLL API 函数】xlfUnregister (Form 1)
    【Excel 4.0 函数】REGISTER 的两种形式以及VBA等效语句
    【Excel 4.0 函数】REGISTER
    【Bochs 官方手册翻译】 第一章 Bochs介绍
  • 原文地址:https://www.cnblogs.com/tangself/p/1624434.html
Copyright © 2011-2022 走看看