如何扩展Koin实现适配Ktor请求生命周期的自定义服务作用域
这个需求早有成熟的生产级实现,完全不需要从零开发底层逻辑,基于Koin原生开放的扩展能力就能实现,不需要修改Koin核心源码。
实现核心依据
Koin本身原生支持自定义作用域(Scope)机制,自带作用域内实例单例绑定、生命周期回调、作用域关闭时自动触发实例销毁方法的能力,你要的请求级作用域本质就是把自定义作用域的生命周期和Ktor的请求生命周期做绑定,整个实现逻辑非常轻量。
具体实现步骤
封装你要的
request<T>DSL
先定义请求作用域的限定符,再给Koin的Module写扩展方法即可,和原生的single/factory写法完全对齐:import org.koin.core.qualifier.named import org.koin.dsl.ScopeDSL import org.koin.dsl.module val requestScopeQualifier = named("KTOR_REQUEST_SCOPE") inline fun <reified T : Any> Module.request( createdAtStart: Boolean = false, noinline definition: ScopeDSL.() -> T ) { scope(requestScopeQualifier) { scoped(createdAtStart = createdAtStart, definition = definition) } }编写Ktor插件绑定请求生命周期
利用Ktor的插件生命周期钩子,在请求进入时创建独立的Koin作用域、绑定到当前请求的属性上,请求处理完成后自动关闭作用域,触发所有request级Bean的销毁逻辑:import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.util.* import org.koin.core.scope.Scope import org.koin.java.KoinJavaComponent.getKoin val KoinRequestScopePlugin = createApplicationPlugin("KoinRequestScope") { val scopeKey = AttributeKey<Scope>("KOIN_REQUEST_SCOPE") onCall { call -> // 给每个请求生成独立的作用域,用请求唯一ID作为作用域ID val requestScope = getKoin().createScope( scopeId = call.request.id, qualifier = requestScopeQualifier ) call.attributes.put(scopeKey, requestScope) } onCallRespond { call, _ -> // 请求响应发送前关闭作用域,自动销毁所有request级实例 call.attributes.getOrNull(scopeKey)?.close() } } // 扩展方法方便在全链路获取请求作用域 val ApplicationCall.requestScope: Scope get() = attributes[AttributeKey("KOIN_REQUEST_SCOPE")]使用方式完全符合你的预期
首先在Ktor应用启动时安装上述插件,之后在Koin模块里就可以直接用你想要的语法定义Bean:val appModule = module { single<CoolService> { CoolServiceImpl() } factory<CoolerService> { CoolerServiceImpl() } request<CoolestService> { CoolestServiceImpl() } }同一个请求链路里不管是在拦截器、路由处理函数、还是其他request级Bean里注入
CoolestService,拿到的都是同一个实例;如果你的Bean实现了AutoCloseable接口,作用域关闭时会自动调用close()方法完成资源释放。
注意事项
- 不要把request作用域的Bean注入到
single/factory级别的Bean中,会出现作用域泄漏,Koin本身会在检测到这类跨作用域注入时抛出异常提醒。 - 这个实现全量基于Koin和Ktor的公开API,没有用到内部私有逻辑,版本兼容性很强,目前已经有大量开发者在生产环境使用同类实现。
内容的提问来源于stack exchange,提问作者FailedUnitTest
相关产品推荐
相关产品推荐

