KtorでDIを使うサンプル実装をした
はじめに
Ktorを使ったときにDIをどのように行うかを試してみました。
準備
KtorでDIをする際のアプローチとして、Koinを使う方法があったので 今回はこれを使います。
insert-koin.io ※KtorというよりかはKotlinでinjectする際のライブラリという感じか
実装
今回は以下のような順で処理をされるイメージの簡単なプログラムを作ってみます。
- Application.ktでrouting
- Controllerからusecaseの処理を呼ぶ
- usecaseで結果を返す(ここからさらにrepositoryを呼ぶなどしたいが、今回はここで固定の文字列を返します)
1. Application.ktでrouting
package com.example import com.example.usecase.HelloInteractor import com.example.usecase.HelloUsecase import com.example.web.HelloController import com.example.web.HelloControllerImpl import io.ktor.application.* import io.ktor.response.* import io.ktor.routing.* import org.koin.dsl.module import org.koin.ktor.ext.Koin import org.koin.ktor.ext.inject fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args) @Suppress("unused") // Referenced in application.conf @kotlin.jvm.JvmOverloads fun Application.module(testing: Boolean = false) { // setting DI install(Koin) { // modulesを設定する。ここに追加したいものを追加する modules(helloModule) } // inject val helloController: HelloController by inject() routing { get("/test") { call.apply { respond("helloTest") } } get("/hello") { call.respondText(helloController.fetch()) } } } // DIの設定 val helloModule = module { single<HelloController> { HelloControllerImpl(get()) } single<HelloUsecase> { HelloInteractor() } }
2. Controllerからusecaseの処理を呼ぶ
package com.example.web import com.example.usecase.HelloUsecase interface HelloController { fun fetch(): String } class HelloControllerImpl( val usecase: HelloUsecase ) : HelloController { override fun fetch(): String { val result = usecase.fetch() return result } }
3. usecaseで結果を返す(ここからさらにrepositoryを呼ぶなどしたいが、今回はここで固定の文字列を返します)
package com.example.usecase interface HelloUsecase { fun fetch(): String } class HelloInteractor : HelloUsecase{ override fun fetch(): String { return "hello usecase result!" } }
まとめ
Application.ktでDIの設定をするコードになっているのでDIする対象が増えてきたときに 本記事の方法だとあまり良くないものになっています。 DIする方法を調べて、とりあえずDIしてみるということを目指して今回は実装してみました。
コードはこちらに。 github.com