Web应用程序初始化如下:
- 众所周知,当 IIS 收到对特定 Asp.net 应用程序资源的第一个请求时,IIS 会创建一个
HttpApplication
实例(在global.asax
代码隐藏中定义) . - 创建此新实例后,它会进行初始化,同时还会检查所有已配置的 HTTP 模块。
- 然后实例化所有模块并将其放入应用程序的
Modules
集合(类型为HttpModuleCollection
) - 循环模块并调用其
Init()
方法(当它们注册请求事件时)
据我了解,上述场景发生在 Web 应用程序启动/初始化时(因此是应用程序启动事件)。
模块会发生什么?
当 Web 应用程序处于事件状态时,它们是否在每个请求上(重新)实例化或在每个连续请求的 Modules
属性中重用?据我了解 IIS 和 Asp.net,它们在 Web 应用程序的整个生命周期中都被重用。
如果它们被重用,我们是否可以假设它们的 Init()
方法实际上是应用程序启动事件的伪事件处理程序?问题是我们无法附加到 http 模块中的应用程序级别事件。但如果它们被重用,我们可以使用 Init()
作为应用程序启动事件,并执行我们在 global.asax
中放入的任何操作。
问题
我们可以假设模块的 Init()
方法仅在应用程序启动事件时调用吗?我们可以使用这个假设来注册其 global.asax
代码隐藏的应用程序的路由吗? web.config
通常是可访问的,我们可以按照我们想要的方式更改它。
这真的有用吗?
其他信息
我们可以检查HttpApplication
代码并检查其InitModulesCommon()
方法。这实际上调用了每个已注册 HTTP 模块的 Init()
。更有趣的是,该方法仅由 InitIntegratedModules()
和 InitModules()
方法使用。它们都仅在 HttpApplication.InitInternal()
方法中使用。这是我的假设的基础,但我想知道是否有人滥用 IHttpModule.Init()
应用程序启动事件。
最佳答案
Init()
仅调用一次(每个 HttpApplication
实例)
经过我的测试,IHttpModule
初始化的内部工作原理如下:
- 每个
IHttpModule
均在 Web 应用程序启动时通过实例化和调用Init()
方法进行初始化 HttpApplication
将所有模块实例存储在其Modules
属性中- 模块会在
HttpApplication
的整个生命周期内重复使用,并且只要应用程序处于事件状态,就不会被丢弃/重新初始化
所以最好的结果是
您无法将 IHttpModule
附加到应用程序级别事件,但您可以使用其 Init()
方法作为伪应用程序启动事件委托(delegate)。在其中,您可以执行通常放入 Global.asax
的 Application_Start
委托(delegate)内的任何代码。
您还可以在我的 blog post 中阅读有关它的详细信息.
但在现实网络服务器环境中要小心
但是 IIS 使用称为“应用程序池”的东西。每个池可以有任意数量的 HttpApplication 实例。是的,多个。应用程序启动会创建所有这些实例。每个模块都会初始化自己的模块列表,但只有第一个执行 Application_OnStart
事件处理程序。
因此,每当您的模块修改某些公共(public)共享资源时,您应该采取额外的措施来表明第一个模块已经完成了该操作,并且其他模块不会再这样做。阅读additional blog post它将向您展示如何以及何时对您的模块使用线程锁定,以使其真正充当 Application_OnStart
事件处理程序。顺便说一句:如果需要,也可以处理 Application_OnEnd
事件。 ;)
详细博客文章链接
关于asp.net - 高级: How many times does HttpModule Init() method get called during application's life?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3370839/