asp.net生命周期一直就想对他彻底的动手搞清楚了。以前一直处于朦朦胧胧的认识状态,今天终于下狠心动手做了个例子来了解生命周期过程。之所以打算自己动手做是因为我一直觉得虽然网上有了类似的例子,不过只有自己亲手做一遍然后通过博客写出来才能使自己更深刻的理解这些内容。好了,不废话了,开始做。
编写代码
先来看一下整个项目的结构以便对我们做的例子有一个大体的了解。项目中我定义了一个module,handler,global和一个页面以及自定义的一个控件。因为有的过程中没法直接使用Response方法,为了记录页面中事件的信息我使用了Logger这个类来专门记录信息,这是类采用了单例设计模式。来看一下他的代码:
public class Logger { private static Logger _logger; private static object _o = new object(); public static String _tempInfo; //记录临时信息,页面卸载后将被清空 public static String _showInfo; //页面卸载时_tempInfo中的信息将被传递过来用于显示 private Logger() { } public static Logger GetInstance() { lock (_o) { if (_logger != null) { return _logger; } else { _logger = new Logger(); return _logger; } } } public void WriteInfo(String info) { _tempInfo += String.Format("<p>{0}</p>",info); } public void WriteInfo(String info,string color) { _tempInfo += String.Format("<p style=\"color:{0};\">{1}</p>", color, info); } }
有了这个类我们就方便了各个过程的记录了。下面就在各个页面中增加记录代码,大概的格式样子是这样子的:
Logger l = Logger.GetInstance(); l.WriteInfo("Application_Start","blue");
同时为了了解自定义控件中的顺序我们自定义了一个简单的控件,它实现了IPostBackDataHandler,IPostBackEventHandler这样就能看到控件回调引起的数据处理和事件处理了。另外自定义的module的Init方法中也被记录了信息(代码就不贴出来了,大家看后面的源码,对module不了解的建议谷歌一下)。
分析结果
将global和页面里面的各个事件都记录信息后运行程序如下:
页面中我放了两个自定义的控件,所以会显示两次。从上面的四幅图我总结了以下几点:
1.Application_Start是指网站重新编译,重启等情况下第一次被人访问时激发。
以后所以都不会被执行到(由1,2,3副图片对比可以看出)也就是说执行且执行一次。通常可以定义一些全局变量。
2.Session_Start是某个用户在某个会话期中第一次访问激发的。
如上图第一副图片中我们在chrome下第一次访问页面session_start被激发,然后再通过chrome访问这个页面时(第二副图片)session_start就不被激发了。而当我们再用firefox打开这个页面时session_start又被激发了。由此可以验证我们的猜想。Session_Start方法通常用于设置某人的一些信息到SESSION,或触发用户访问计数等
3.Application_BeginRequest,Application_BeginRequest每次请求,不管用户是不是第一次访问,页面是不是回发等等。
利用这个特点一般可以在Application_BeginRequest中进行URL重写。而Application_BeginRequest看名字也知道了,可以在其中进行权限验证等等操作。
4.控件数据回发的流程
页面OnInit事件中调用各个控件的LoadPostData方法加载从页面发过来的控件值。然后在Page_Load后调用各个控件的RaisePostDataChangedEvent的事件(我们在LoadPostData人为返回了TRUE,所以该方法一定会被执行)来完成对应的数据更改事件。
5.控件事件回发触发的时机
从第三幅图可以看到控件是在数据回发事件后进行的。这点也可以从第二副图看出来,Button1_click事件就在数据回发后进行的。笼统一点说就是控件的状态更改都在page_load后进行。
6.为什么Application_BeginRequest会执行两次?
大家也看到了,很奇怪的是我们明明就请求了一个页面,页面中也没有其他的图片请求。为什么Application_BeginRequest会被执行了两次呢?!既然他请求,那我们看看他到底在请求什么就是了?在Application_BeginRequest代码中将”HttpContext.Current.Request.Path”记录显示文件中。然后执行显示如下:
以前也一直没有注意到这方面的内容。原来默认回去请求网站的图标啊。没文化了^_^!我找了个图片放到网站根目录下,再次刷新浏览器有效果了:
7.整个页面的执行过程
第一副图就是最好的例子,不过感觉还是要再总结一下(可能事件有点少,不过重要的都画出来了):
还没有结束
上面只是从我们的编码能够涉及到的地方看了下asp.net的执行流程。那么在这之前呢?就是从IIS接受到这个请求到我们上面讲到的这之间的过程又是如何的呢?
借用网上的一张图片来说明一下:IIS会首先根据请求地址的映射将其提交到aspnet_isapi.dll(具体的映射关系可以在IIS中设置),然后经过中间的一些COM组件(详细说起来还是蛮复杂的,具体可以看这篇文章)到达ISApiRuntime,在这里请求将会被路由到ISAPIRuntime.ProcessRequest()方法里。这个方法会接着调用HttpRuntime.ProcessRequest,这个方法会为请求创建了一个新的HttpContext实例然后获取一个HttpApplication实例并调用HttpApplication.Init()初始化管道事件。于是这样就到了我们上面的Global.ascx定义的各个方法中。
看起来可能简单,不过还是很复杂的。这些过程都不是我们能够控制的,所以我觉得了解一下就可以了。真正掌握的还是上面的几个过程。
好了,说的也差不多了。以后这上面有新的体会再补充吧。奉上测试代码!