KtorでDIを使うサンプル実装をした

はじめに

Ktorを使ったときにDIをどのように行うかを試してみました。

準備

KtorでDIをする際のアプローチとして、Koinを使う方法があったので 今回はこれを使います。

insert-koin.io ※KtorというよりかはKotlinでinjectする際のライブラリという感じか

実装

今回は以下のような順で処理をされるイメージの簡単なプログラムを作ってみます。

  1. Application.ktでrouting
  2. Controllerからusecaseの処理を呼ぶ
  3. 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