ASP.NET Core MVC过滤器是否为单例?验证与疑问
关于ASP.NET Core MVC过滤器生命周期的问题解答
嘿,你的观察完全正确!先给你一个清晰的结论:不是所有过滤器都是单例,但你用属性形式定义的过滤器(比如你的AuthorizationFilterAttribute)默认确实是单例,在应用生命周期内仅创建一次。下面给你详细拆解不同场景下的过滤器生命周期规则:
1. 属性式过滤器(你的代码场景)
当你通过[AuthorizationFilter]这种属性形式把过滤器标注在控制器或动作方法上时,ASP.NET Core MVC会在应用启动阶段就扫描并缓存这些过滤器的实例——这就是为什么你的构造函数只被调用一次,而OnAuthorization会在每次HTTP请求时执行(复用同一个实例处理请求)。
这种设计是为了性能优化,避免每次请求都重复创建过滤器实例,但这里要注意一个关键陷阱:单例过滤器不能依赖Scoped或Transient生命周期的服务(比如DbContext),否则会导致这些服务被长期持有,出现数据一致性问题或资源泄漏。
2. 其他过滤器注册方式的生命周期
过滤器的生命周期并不固定,完全取决于你注册/使用它的方式:
- 全局过滤器(直接添加类型):如果在
Program.cs里通过builder.Services.AddControllers(options => options.Filters.Add<MyFilter>())添加,默认是单例,应用启动时创建一次,复用至应用停止。 - ServiceFilter方式:用
[ServiceFilter(typeof(MyFilter))]标注,或者全局添加options.Filters.AddService<MyFilter>(),此时过滤器的生命周期由你在DI容器中的注册决定——你可以注册为Scoped(每次请求创建新实例)、Transient(每次获取创建新实例)或Singleton(单例)。 - TypeFilter方式:用
[TypeFilter(typeof(MyFilter))]标注,默认是每次请求创建一个新的过滤器实例(相当于Transient生命周期),而且支持直接在过滤器构造函数中注入依赖,不需要提前注册到DI容器。
3. 不同过滤器接口的共性
不管是IAuthorizationFilter、IActionFilter、IResourceFilter还是IExceptionFilter,它们的生命周期规则都是一致的——只和注册/使用方式有关,和接口类型本身无关。比如你如果用TypeFilter注册一个IActionFilter,它也会每次请求创建新实例。
总结一下:你的构造函数仅执行一次是因为属性式过滤器默认单例,但并不是所有过滤器都是单例,具体生命周期由你选择的注册方式决定。
内容的提问来源于stack exchange,提问作者Scott.Hu
相关产品推荐
相关产品推荐

