Iris 中依赖默认为单例,需显式指定 iris.ScopeRequest 实现请求级生命周期;控制器亦为单例,请求数据须通过方法参数传入或 BeforeActivation 钩子动态注入。

注册依赖时必须显式指定 iris.ScopeRequest
Iris 默认所有 app.Register 注册的依赖都是单例(Singleton),整个应用生命周期只创建一次。控制器方法里拿到的永远是同一个实例,不适合带请求上下文、用户身份或临时状态的对象。
若需每次 HTTP 请求都新建一个依赖(比如带 ctx.Request().Context() 的数据库事务对象、带 session 的 auth service),必须主动传入 iris.ScopeRequest 选项:
app.Register(NewRequestScopedService, iris.ScopeRequest)- 该依赖会在每次请求开始时调用
NewRequestScopedService构造函数,结束时自动销毁(前提是类型实现了io.Closer或有自定义清理逻辑) - 不加这个选项,哪怕你在控制器里 new 出来再注入,也逃不过被框架当成单例复用的命运
控制器自身不是按请求创建的,别在结构体字段里存 request-bound 数据
Iris 的 MVC 控制器默认是 Singleton —— 整个应用只初始化一次,所有请求共用同一个 controller 实例。这意味着:
- 不能把
iris.Context、http.Request或基于它们构造的临时对象直接存成 controller 字段(如type UserCtrl struct { Ctx iris.Context }),否则高并发下会严重错乱 - 字段适合放 service、client、config 等无状态或线程安全的依赖(如
db *sql.DB、cache *redis.Client) - 真正属于请求的数据,必须通过方法参数传入(
func (c *UserCtrl) GetByID(ctx iris.Context, id int64))或在方法内按需构造
用 BeforeActivation 钩子做请求级依赖预处理
如果某些依赖需要在每次请求前动态绑定(比如根据 header 解析 tenant ID 后初始化租户专属 client),不能靠 app.Register 一次性注册,得在控制器激活阶段介入:
- 在 controller 中实现
BeforeActivation(b mvc.BeforeActivation) - 在钩子里调用
b.Dependencies().Add(func(ctx iris.Context) *TenantClient { return NewTenantClient(ctx) }) - 这个函数会在每次请求进入 controller 方法前执行,返回的对象只对该次请求有效
- 注意:该函数签名必须接收
iris.Context,且不能有其他未被 Iris 自动注入的参数,否则 panic
别指望 BeginRequest/EndRequest 做资源生命周期管理
这两个钩子只是请求生命周期回调,Iris 不会自动帮你 close 或 dispose 任何对象:
-
BeginRequest可用于记录日志、设置 traceID、初始化 context.Value,但不会触发依赖构造 -
EndRequest可用于打点、回收非托管资源(如手动defer conn.Close()),但无法替代ScopeRequest的自动释放机制 - 如果你在
BeginRequest里 new 了一个 DB transaction,必须在EndRequest或方法内显式tx.Commit()/tx.Rollback(),Iris 不会代劳


















