asp.net运行原理 详解
程序员文章站
2024-03-07 08:48:56
主要类: system.web.httpruntime system.web.httpapplicationfactory system.web.httpapp...
主要类:
system.web.httpruntime
system.web.httpapplicationfactory
system.web.httpapplication
system.web.compilation.buildmanager
system.web.compilation.applicationbuildprovider
system.web.compilation.buildproviderscompiler
system.web.ui.pagehandlerfactory
请求处理简要流程图:
阅读建议:
用reflector工具边查看asp.net 2.0的源代码边阅读。
分析:
当我们通过浏览器向asp.net 2.0网站的一个asp.net页面发起请求时,在服务器端首先是iis收到请求,iis一看是asp.net页面,心里很开心,因为这个请求不用它处理,交给asp.net isapi就行了。asp.net isapi的工作也比较轻松,他的主要任务就是安排aspnet_wp.exe处理请求,并监视aspnet_wp.exe进程的执行情况,如果aspnet_wp.exe进程太累了,不能出色地完成任务,asp.net isapi就要让他下岗,换一个新的aspnet_wp.exe来处理工作。
aspnet_wp.exe的主要任务是将请求交给一系列称为的 http 管道的托管对象。如果把asp.net isapi比做销售经理,那aspnet_wp.exe就是生产经理,而http 管道就是生产的流水线。负责流水线的小组就是httpruntime,生产经理aspnet_wp.exe会将订单(http请求)交给httpruntime小组的工作人员processrequest(httpworkerrequest wr),httpruntime根据内部的分工,最终由processrequestinternal(httpworkerrequest wr)在流水线上进行生产,所以processrequestinternal(httpworkerrequest wr)是我们分析的重点。
processrequestinternal的主要工作是:
1. 创建httpcontext实例。
2. 对第一次请求进行初始化(ensurefirstrequestinit)。
a) 在ensurefirstrequestinit中通过调用system.web.httpruntime.firstrequestinit进行一些初始化工作,比如:将web.config配置读到到runtimeconfig中,从bin目录中装载所有dll文件。
3. 创建httpwriter实例。
4. 通过调用httpapplicationfactory.getapplicationinstance创建httpapplication实例。
在httpapplicationfactory.getapplicationinstance中有三个关键方法:
httpapplicationfactory._theapplicationfactory.ensureinited();
httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);
httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);
下面我们对这三个方法逐个进行分析:
1) httpapplicationfactory._theapplicationfactory.ensureinited();
该方法检查httpapplicationfactory是否被初始化,如果没有,就通过httpapplicationfactory.init()进行初始化。
在init()中,先获取global.asax文件的完整路径,然后调用compileapplication()对global.asax进行编译。
那编译是如何进行的呢?
编译的工作由buildmanager完成的。buildmanager先得到globalasaxtype(也就是httpapplication),然后调用buildmanager.getglobalasaxbuildresult()=》getglobalasaxbuildresultinternal()=》ensuretoplevelfilescompiled()进行编译。
在ensuretoplevelfilescompiled中,先进行compilationstage.toplevelfiles编译,对下面三个目录中的文件进行编译:
a. compileresourcesdirectory();
编译app_globalresources目录。
b. compilewebrefdirectory();
编译app_webreferences目录。
c. compilecodedirectories();
编译app_code目录。
接着进行compilationstage.globalasax 编译,对global.asax进行编译,方法调用情况:compileglobalasax()=》applicationbuildprovider.getglobalasaxbuildresult(buildmanager.isprecompiledapp)。
在getglobalasaxbuildresult中具体的编译是由applicationbuildprovider与buildproviderscompiler共同完成的。
buildproviderscompiler.performbuild();进行编译工作。
applicationbuildprovider.getbuildresult得到编译的结果。
编译成功后,会在c:\windows\microsoft.net\framework\v2.0.50727\temporary asp.net files\相应的目录中生成类似app_global.asax.mlgx7n2v.dll的dll文件。
编译生成的类名为asp.global_asax,继承自httpapplication。
注:如果web目录中没有global.asax文件,就不会编译生成app_global.asax.mlgx7n2v.dll这样的文件。
2) httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);
创建特定的httpapplication实例,触发applicationonstart事件,执行asp.global_asax中的application_start(object sender, eventargs e)方法。这里创建的httpapplication实例在处理完事件后,就被回收。
3) httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);
该方法创建httpapplication实例并进行初始化(调用system.web.httpapplication. initinternal()方法)。
创建httpapplication实例是根据实际的_theapplicationtype进行创建。如果web目录中没有global.asa文件,也就是说没有动态编译生成asp.global_asax类型,那就直接实例化httpapplication。如果创建了asp.global_asax类型,那就对asp.global_asa进行实例化。
创建httpapplication实例之后就是调用实例的initinternal方法。
initinternal方法也是我们重点分析的方法,该方法的主要功能如下:
1. initmodules():根据web.config的设置,创建相应的httpmodules。
2. hookupeventhandlersforappplicationandmodules:根据发生的事件,调用httpapplication实例中相应的事件处理函数。
3. 创建很多实现iexecutionstep接口的类的实例并添加到当前httpapplication实例的_execsteps中,等待回调时执行。从这里我们可以看到httpapplication是以异步的方式处理请求,对请求的很多处理工作都放入了_execstep等待回调时执行。
_execstep中主要的处理工作如下:
1) 对请求的路径进行安全检查,禁止非法路径访问(validatepathexecutionstep)。
2) 如果设置了urlmappings, 进行rewritepath(urlmappingsexecutionstep)。
3) 执行事件处理函数,比如:beginrequest、authenticaterequest等等。
4) 获取处理当前请求的httphandler,asp.net页面的运行时编译也是在这里进行的。(maphandlerexecutionstep)
该处理是通过调用system.web.httpapplication. maphttphandler方法。
在maphttphandler中,首先根据访问的地址从web.config获取相应的实现ihttphandlerfactory的类型。对于asp.net页面,默认是pagehanlderfactory。然后创建pagehanlderfactory实例,调用gethandlerhelper,在gethandlerhelper中调用buildmanager.createinstancefromvirtualpath编译并创建当前请求的asp.net页面的实例(如果已经编译过,直接从缓存中加载)。
createinstancefromvirtualpath经过几次方法调用,将编译任务给了buildmanager. compilewebfile()。compilewebfile从web.config得到相应的buildprovider,对于.aspx文件,相应的buildprovider是pagebuildprovider。pagebuildprovider是如何进行页面编译的,这里就不再就进一步分析了,如果你感兴趣,可以进一步研究asp.net 2.0的源代码。
5) 调用相应httphandler的.processrequest方法处理请求(如果是异步方式,调用beginprocessreques)。(callhandlerexecutionstep)
6) 将响应内容写入filter。(callfilterexecutionstep)
5. 调用httpapplication实例的beginprocessrequest异步处理请求。
上面所讲的_execsteps中所发生的许多事情,都是在httpruntime调用httpapplication beginprocessrequest之后,在beginprocessrequest中调用resumesteps后执行的。
asp.net 2.0运行时是asp.net 2.0中非常复杂、难以理解也是很重要的部分,对asp.net 2.0运行时源代码的研究有处于我们加深对asp.net 2.0原理的理解,会给我们开发asp.net 2.0应用程序带来不少帮助。这篇文章是我初次学习asp.net 2.0运行时,为了帮助自己更好地理解asp.net 2.0运行时而写的,欢迎你对文章内容提出批评与建议。
system.web.httpruntime
system.web.httpapplicationfactory
system.web.httpapplication
system.web.compilation.buildmanager
system.web.compilation.applicationbuildprovider
system.web.compilation.buildproviderscompiler
system.web.ui.pagehandlerfactory
请求处理简要流程图:
阅读建议:
用reflector工具边查看asp.net 2.0的源代码边阅读。
分析:
当我们通过浏览器向asp.net 2.0网站的一个asp.net页面发起请求时,在服务器端首先是iis收到请求,iis一看是asp.net页面,心里很开心,因为这个请求不用它处理,交给asp.net isapi就行了。asp.net isapi的工作也比较轻松,他的主要任务就是安排aspnet_wp.exe处理请求,并监视aspnet_wp.exe进程的执行情况,如果aspnet_wp.exe进程太累了,不能出色地完成任务,asp.net isapi就要让他下岗,换一个新的aspnet_wp.exe来处理工作。
aspnet_wp.exe的主要任务是将请求交给一系列称为的 http 管道的托管对象。如果把asp.net isapi比做销售经理,那aspnet_wp.exe就是生产经理,而http 管道就是生产的流水线。负责流水线的小组就是httpruntime,生产经理aspnet_wp.exe会将订单(http请求)交给httpruntime小组的工作人员processrequest(httpworkerrequest wr),httpruntime根据内部的分工,最终由processrequestinternal(httpworkerrequest wr)在流水线上进行生产,所以processrequestinternal(httpworkerrequest wr)是我们分析的重点。
processrequestinternal的主要工作是:
1. 创建httpcontext实例。
2. 对第一次请求进行初始化(ensurefirstrequestinit)。
a) 在ensurefirstrequestinit中通过调用system.web.httpruntime.firstrequestinit进行一些初始化工作,比如:将web.config配置读到到runtimeconfig中,从bin目录中装载所有dll文件。
3. 创建httpwriter实例。
4. 通过调用httpapplicationfactory.getapplicationinstance创建httpapplication实例。
在httpapplicationfactory.getapplicationinstance中有三个关键方法:
httpapplicationfactory._theapplicationfactory.ensureinited();
httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);
httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);
下面我们对这三个方法逐个进行分析:
1) httpapplicationfactory._theapplicationfactory.ensureinited();
该方法检查httpapplicationfactory是否被初始化,如果没有,就通过httpapplicationfactory.init()进行初始化。
在init()中,先获取global.asax文件的完整路径,然后调用compileapplication()对global.asax进行编译。
那编译是如何进行的呢?
编译的工作由buildmanager完成的。buildmanager先得到globalasaxtype(也就是httpapplication),然后调用buildmanager.getglobalasaxbuildresult()=》getglobalasaxbuildresultinternal()=》ensuretoplevelfilescompiled()进行编译。
在ensuretoplevelfilescompiled中,先进行compilationstage.toplevelfiles编译,对下面三个目录中的文件进行编译:
a. compileresourcesdirectory();
编译app_globalresources目录。
b. compilewebrefdirectory();
编译app_webreferences目录。
c. compilecodedirectories();
编译app_code目录。
接着进行compilationstage.globalasax 编译,对global.asax进行编译,方法调用情况:compileglobalasax()=》applicationbuildprovider.getglobalasaxbuildresult(buildmanager.isprecompiledapp)。
在getglobalasaxbuildresult中具体的编译是由applicationbuildprovider与buildproviderscompiler共同完成的。
buildproviderscompiler.performbuild();进行编译工作。
applicationbuildprovider.getbuildresult得到编译的结果。
编译成功后,会在c:\windows\microsoft.net\framework\v2.0.50727\temporary asp.net files\相应的目录中生成类似app_global.asax.mlgx7n2v.dll的dll文件。
编译生成的类名为asp.global_asax,继承自httpapplication。
注:如果web目录中没有global.asax文件,就不会编译生成app_global.asax.mlgx7n2v.dll这样的文件。
2) httpapplicationfactory._theapplicationfactory.ensureappstartcalled(context);
创建特定的httpapplication实例,触发applicationonstart事件,执行asp.global_asax中的application_start(object sender, eventargs e)方法。这里创建的httpapplication实例在处理完事件后,就被回收。
3) httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(context);
该方法创建httpapplication实例并进行初始化(调用system.web.httpapplication. initinternal()方法)。
创建httpapplication实例是根据实际的_theapplicationtype进行创建。如果web目录中没有global.asa文件,也就是说没有动态编译生成asp.global_asax类型,那就直接实例化httpapplication。如果创建了asp.global_asax类型,那就对asp.global_asa进行实例化。
创建httpapplication实例之后就是调用实例的initinternal方法。
initinternal方法也是我们重点分析的方法,该方法的主要功能如下:
1. initmodules():根据web.config的设置,创建相应的httpmodules。
2. hookupeventhandlersforappplicationandmodules:根据发生的事件,调用httpapplication实例中相应的事件处理函数。
3. 创建很多实现iexecutionstep接口的类的实例并添加到当前httpapplication实例的_execsteps中,等待回调时执行。从这里我们可以看到httpapplication是以异步的方式处理请求,对请求的很多处理工作都放入了_execstep等待回调时执行。
_execstep中主要的处理工作如下:
1) 对请求的路径进行安全检查,禁止非法路径访问(validatepathexecutionstep)。
2) 如果设置了urlmappings, 进行rewritepath(urlmappingsexecutionstep)。
3) 执行事件处理函数,比如:beginrequest、authenticaterequest等等。
4) 获取处理当前请求的httphandler,asp.net页面的运行时编译也是在这里进行的。(maphandlerexecutionstep)
该处理是通过调用system.web.httpapplication. maphttphandler方法。
在maphttphandler中,首先根据访问的地址从web.config获取相应的实现ihttphandlerfactory的类型。对于asp.net页面,默认是pagehanlderfactory。然后创建pagehanlderfactory实例,调用gethandlerhelper,在gethandlerhelper中调用buildmanager.createinstancefromvirtualpath编译并创建当前请求的asp.net页面的实例(如果已经编译过,直接从缓存中加载)。
createinstancefromvirtualpath经过几次方法调用,将编译任务给了buildmanager. compilewebfile()。compilewebfile从web.config得到相应的buildprovider,对于.aspx文件,相应的buildprovider是pagebuildprovider。pagebuildprovider是如何进行页面编译的,这里就不再就进一步分析了,如果你感兴趣,可以进一步研究asp.net 2.0的源代码。
5) 调用相应httphandler的.processrequest方法处理请求(如果是异步方式,调用beginprocessreques)。(callhandlerexecutionstep)
6) 将响应内容写入filter。(callfilterexecutionstep)
5. 调用httpapplication实例的beginprocessrequest异步处理请求。
上面所讲的_execsteps中所发生的许多事情,都是在httpruntime调用httpapplication beginprocessrequest之后,在beginprocessrequest中调用resumesteps后执行的。
asp.net 2.0运行时是asp.net 2.0中非常复杂、难以理解也是很重要的部分,对asp.net 2.0运行时源代码的研究有处于我们加深对asp.net 2.0原理的理解,会给我们开发asp.net 2.0应用程序带来不少帮助。这篇文章是我初次学习asp.net 2.0运行时,为了帮助自己更好地理解asp.net 2.0运行时而写的,欢迎你对文章内容提出批评与建议。
上一篇: ASP.NET 站点地图(sitemap)简明教程
下一篇: Android接收和发送短信的实现代码