虽然HttpModule应用的非常广泛,但是我们基本上没有考虑过HttpModule的生存周期。在写这篇文章之前,我一直认为HttpModule 对象的生存周期与Application的生存周期一致,也就是一个Application中只有一个HttpModule。但是通过我对微软的代码进行反射分析,发现HttpModule的生存周期与HttpApplication的生存周期是一致的,代码如下:
1 internal void InitInternal()
2 {
3 this._state = state;
4 PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
5 this._initContext = context;
6 this._initContext.ApplicationInstance = this;
7 try
8 {
9 try
10 {
11 context.ConfigPath = context.Request.ApplicationPath;
12 using (HttpContextWrapper wrapper = new HttpContextWrapper(context))
13 {
14 this.InitModules();
15 if (handlers != null)
16 {
17 this.HookupEventHandlersForAppplicationAndModules(handlers);
18 }
19 this._context = context;
20 this._hideRequestResponse = true;
21 try
22 {
23 this.Init();
24 }
25 catch (Exception exception)
26 {
27 this.RecordError(exception);
28 }
29 }
30![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
31
32 private void InitModules()
33 {
34 HttpModulesConfiguration appConfig =
(HttpModulesConfiguration) HttpContext.GetAppConfig("system.web/httpModules");
35 if (appConfig == null)
36 {
37 throw new HttpException(HttpRuntime.FormatResourceString("Missing_modules_config"));
38 }
39 this._moduleCollection = appConfig.CreateModules();
40 int count = this._moduleCollection.Count;
41 for (int i = 0; i < count; i++)
42 {
43 this._moduleCollection[i].Init(this);
44 }
45 GlobalizationConfig config = (GlobalizationConfig) HttpContext.GetAppConfig("system.web/globalization");
46 if (config != null)
47 {
48 this._appLevelCulture = config.Culture;
49 this._appLevelUICulture = config.UICulture;
50 }
51 }
通过代码可以发现每次创建HttpApplication的时候都回初始化HttpModule。接下来我们在看HttpApplication的生存周期,代码如下:HttpRuntime类的ProcessRequest方法,这个方法是Web请求的入口方法。2 {
3 this._state = state;
4 PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
5 this._initContext = context;
6 this._initContext.ApplicationInstance = this;
7 try
8 {
9 try
10 {
11 context.ConfigPath = context.Request.ApplicationPath;
12 using (HttpContextWrapper wrapper = new HttpContextWrapper(context))
13 {
14 this.InitModules();
15 if (handlers != null)
16 {
17 this.HookupEventHandlersForAppplicationAndModules(handlers);
18 }
19 this._context = context;
20 this._hideRequestResponse = true;
21 try
22 {
23 this.Init();
24 }
25 catch (Exception exception)
26 {
27 this.RecordError(exception);
28 }
29 }
30
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
31
32 private void InitModules()
33 {
34 HttpModulesConfiguration appConfig =
(HttpModulesConfiguration) HttpContext.GetAppConfig("system.web/httpModules");
35 if (appConfig == null)
36 {
37 throw new HttpException(HttpRuntime.FormatResourceString("Missing_modules_config"));
38 }
39 this._moduleCollection = appConfig.CreateModules();
40 int count = this._moduleCollection.Count;
41 for (int i = 0; i < count; i++)
42 {
43 this._moduleCollection[i].Init(this);
44 }
45 GlobalizationConfig config = (GlobalizationConfig) HttpContext.GetAppConfig("system.web/globalization");
46 if (config != null)
47 {
48 this._appLevelCulture = config.Culture;
49 this._appLevelUICulture = config.UICulture;
50 }
51 }
注意:一个HttpRuntime对应一个WebApplication。在Windows2003下(IIS6),下一个w3wp.exe对应一个ApplicationPool,一个ApplicationPool中可以容纳多个WebApplication,每一个WebApplication对应一个AppDomain。如果是XP的话所有的WebApplication都处于iis_asp.exe(名字记得不太清楚了)这个进程中,使用AppDomain来分隔不同的AppDomain.
1 public static void ProcessRequest(HttpWorkerRequest wr)
2 {
3 InternalSecurityPermissions.AspNetHostingPermissionLevelMedium.Demand();
4 if (wr == null)
5 {
6 throw new ArgumentNullException("custom");
7 }
8 RequestQueue queue = _theRuntime._requestQueue;
9 if (queue != null)
10 {
11 wr = queue.GetRequestToExecute(wr);
12 }
13 if (wr != null)
14 {
15 CalculateWaitTimeAndUpdatePerfCounter(wr);
16 ProcessRequestNow(wr);
17 }
18 }
注意下划线标注出来的两个方法。其中GetRequestToExecute方法去检查当前的线程池,判断是否有空闲的线程来处理这个请求,如果没有空闲的线程处理这个请求则将请加入到等待请求队列。接下来我们进一步的分析ProcessRequestNow这个方法。我们最终可以追踪到请求最终在HttpRuntime类的ProcessRequestInternal方法中被处理,代码如下:2 {
3 InternalSecurityPermissions.AspNetHostingPermissionLevelMedium.Demand();
4 if (wr == null)
5 {
6 throw new ArgumentNullException("custom");
7 }
8 RequestQueue queue = _theRuntime._requestQueue;
9 if (queue != null)
10 {
11 wr = queue.GetRequestToExecute(wr);
12 }
13 if (wr != null)
14 {
15 CalculateWaitTimeAndUpdatePerfCounter(wr);
16 ProcessRequestNow(wr);
17 }
18 }
1 private void ProcessRequestInternal(HttpWorkerRequest wr)
2 {
3 HttpContext extraData = new HttpContext(wr, false);
4 wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, extraData);
5 Interlocked.Increment(ref this._activeRequestCount);
6 try
7 {
8 if (this._beforeFirstRequest)
9 {
10 lock (this)
11 {
12 if (this._beforeFirstRequest)
13 {
14 this._firstRequestStartTime = DateTime.UtcNow;
15 this.FirstRequestInit(extraData);
16 this._beforeFirstRequest = false;
17 }
18 }
19 }
20 extraData.Impersonation.Start(true, false);
21 try
22 {
23 extraData.Response.InitResponseWriter();
24 }
25 finally
26 {
27 extraData.Impersonation.Stop();
28 }
29 IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(extraData);
30 if (applicationInstance == null)
31 {
32 throw new HttpException(FormatResourceString("Unable_create_app_object"));
33 }
34 if (applicationInstance is IHttpAsyncHandler)
35 {
36 IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
37 extraData.AsyncAppHandler = handler2;
38 handler2.BeginProcessRequest(extraData, this._handlerCompletionCallback, extraData);
39 }
40 else
41 {
42 applicationInstance.ProcessRequest(extraData);
43 this.FinishRequest(extraData.WorkerRequest, extraData, null);
44 }
45 }
46 catch (Exception exception)
47 {
48 extraData.Response.InitResponseWriter();
49 this.FinishRequest(wr, extraData, exception);
50 }
51 }
我们继续来关注HttpApplicationFactory.GetApplicationInstance(extraData)这个代码。继续追踪,最终定位到HttpApplicationFactory类的GetNormalApplicationInstance方法和CreateNonPublicInstance方法,代码如下:2 {
3 HttpContext extraData = new HttpContext(wr, false);
4 wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, extraData);
5 Interlocked.Increment(ref this._activeRequestCount);
6 try
7 {
8 if (this._beforeFirstRequest)
9 {
10 lock (this)
11 {
12 if (this._beforeFirstRequest)
13 {
14 this._firstRequestStartTime = DateTime.UtcNow;
15 this.FirstRequestInit(extraData);
16 this._beforeFirstRequest = false;
17 }
18 }
19 }
20 extraData.Impersonation.Start(true, false);
21 try
22 {
23 extraData.Response.InitResponseWriter();
24 }
25 finally
26 {
27 extraData.Impersonation.Stop();
28 }
29 IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(extraData);
30 if (applicationInstance == null)
31 {
32 throw new HttpException(FormatResourceString("Unable_create_app_object"));
33 }
34 if (applicationInstance is IHttpAsyncHandler)
35 {
36 IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
37 extraData.AsyncAppHandler = handler2;
38 handler2.BeginProcessRequest(extraData, this._handlerCompletionCallback, extraData);
39 }
40 else
41 {
42 applicationInstance.ProcessRequest(extraData);
43 this.FinishRequest(extraData.WorkerRequest, extraData, null);
44 }
45 }
46 catch (Exception exception)
47 {
48 extraData.Response.InitResponseWriter();
49 this.FinishRequest(wr, extraData, exception);
50 }
51 }
1 private HttpApplication GetNormalApplicationInstance(HttpContext context)
2 {
3 HttpApplication application = null;
4 lock (this._freeList)
5 {
6 if (this._numFreeAppInstances > 0)
7 {
8 application = (HttpApplication) this._freeList.Pop();
9 this._numFreeAppInstances--;
10 }
11 }
12 if (application == null)
13 {
14 application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
15 context.Impersonation.Start(true, false);
16 try
17 {
18 try
19 {
20 application.InitInternal(context, this._state, this._eventHandlerMethods);
21 return application;
22 }
23 finally
24 {
25 context.Impersonation.Stop();
26 }
27 }
28 catch
29 {
30 throw;
31 }
32 }
33 return application;
34 }
35
36 internal static object CreateNonPublicInstance(Type type)
37 {
38 return CreateNonPublicInstance(type, null);
39 }
2 {
3 HttpApplication application = null;
4 lock (this._freeList)
5 {
6 if (this._numFreeAppInstances > 0)
7 {
8 application = (HttpApplication) this._freeList.Pop();
9 this._numFreeAppInstances--;
10 }
11 }
12 if (application == null)
13 {
14 application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
15 context.Impersonation.Start(true, false);
16 try
17 {
18 try
19 {
20 application.InitInternal(context, this._state, this._eventHandlerMethods);
21 return application;
22 }
23 finally
24 {
25 context.Impersonation.Stop();
26 }
27 }
28 catch
29 {
30 throw;
31 }
32 }
33 return application;
34 }
35
36 internal static object CreateNonPublicInstance(Type type)
37 {
38 return CreateNonPublicInstance(type, null);
39 }
1 private void RecycleNormalApplicationInstance(HttpApplication app)
2 {
3 if (this._numFreeAppInstances < 100)
4 {
5 lock (this._freeList)
6 {
7 this._freeList.Push(app);
8 this._numFreeAppInstances++;
9 return;
10 }
11 }
12 app.DisposeInternal();
13 }
14
15
16 private void RecycleSpecialApplicationInstance(HttpApplication app)
17 {
18 if (this._numFreeSpecialAppInstances < 20)
19 {
20 lock (this._specialFreeList)
21 {
22 this._specialFreeList.Push(app);
23 this._numFreeSpecialAppInstances++;
24 }
25 }
26 }
2 {
3 if (this._numFreeAppInstances < 100)
4 {
5 lock (this._freeList)
6 {
7 this._freeList.Push(app);
8 this._numFreeAppInstances++;
9 return;
10 }
11 }
12 app.DisposeInternal();
13 }
14
15
16 private void RecycleSpecialApplicationInstance(HttpApplication app)
17 {
18 if (this._numFreeSpecialAppInstances < 20)
19 {
20 lock (this._specialFreeList)
21 {
22 this._specialFreeList.Push(app);
23 this._numFreeSpecialAppInstances++;
24 }
25 }
26 }