wakwak3125's blog

年に数回更新する予定のブログ。 AndroidとかKotlinとかJavaとか。

Koinから環境変数を利用する

f:id:wakwak3125:20191212223809j:plain

こんにちは、普段はAndroidでKotlinを書いている人間です。 この記事は Kotlin Advent Calendar 2019 13日目の記事です。

最近、Kotlinサーバサイドにチャレンジをしているのですがその際に、環境変数の扱いをどうするのが良いのかと言うことについて考えていましたが、 Koinと言うDIコンテナの機能を利用すると便利にできそうだなと思ったので、Koinの紹介を軽くしてから、そのTipsを共有したいと思います。 なお、本記事執筆の際に利用した環境は以下の通りです。

  • Kotlin: 1.3.60
  • Koin: 2.0.1

まずKoinについて

KoinはKotlinで書かれた軽量でシンプルなDIコンテナです。 導入に関しては、ドキュメントをみていただくのが最適だと思うので、ドキュメントへのリンクを案内させていただきます。

https://insert-koin.io/

Koinはそのままでももちろん、AndroidやKtorとも連携してシンプルにDIを行うことができます。

環境変数を出力するアプリケーションを作ってみる

今回は、環境変数printlnする小さなアプリケーションを作りながら解説します。 環境変数にはMESSAGEが設定されており、値にはHello, World!と書かれています。 この環境変数を出力するアプリケーションを作っていきます。 まずはKoinを使わずにやる 通常の方法でやった場合がこちらです。

fun main() {
    println(System.getenv("MESSAGE"))
}

はい、これ表示できました。ではKoinを使ってこれを置き換えていきましょう。

Koinを使う方法 環境変数を格納するクラスを用意します。今回はConfigと言うクラスにします。

data class Config(val message: String)

このクラスをInjectすることで、環境変数のDIを実現していきます。 次に、このクラスをmoduleに追加します。

val module = module {
    single { Config(getProperty("MESSAGE")) }
}

ここのsingleブロック内のthisScopeと呼ばれるクラスです。 このScopeには

  • fun <T> getProperty(key: String, defaultValue: T): T
  • fun <T> getProperty(key: String): T
  • fun <T> getPropertyOrNull(key: String): T?

と言う3つの関数が用意されており、このkey環境変数の名前を指定してあげることで取得できる仕組みとなっています。

getPropertyの内部実装は、PropertyRegistryへのデリゲートとなっています。PropertyRegistryへどのようにして環境変数が格納されるかについては後述します。

次に、このConfigを利用するクラスを作ります。

class MainComponent : KoinComponent {
    private val config by inject<Config>()
    fun sayMessage() {
        println(config.message)
    }
}

あとはこのmoduleをKoinの初期化時に渡します。 ここで忘れてはいけないのが、environmentPropertiesの呼び出しです。 ここで呼び出さないと環境変数はKoinのpropertyRegistryに登録されません。

environmentPropertiesの中では、System.getProperties()System.getenv()を呼び出し、そこで取得した値をPropertyRegistryの中に保持します。

このenvironmentPropertiesの動きを少しみてみます。 この関数はKoinApplicationクラスに実装されている関数で、内部でKoinPropertyRegistryへ接続し、PropertyRegistryloadEnvironmentPropertiesへと処理をデリゲートしています。

KoinApplication#environmentProperties()Koin#getPropertyRegistry()PropertyRegistry#loadEnvironmentProperties() と言う流れです。

より内部の詳細が気になる方はこちらをご覧ください。

https://github.com/InsertKoinIO/koin/blob/master/koin-projects/koin-core/src/main/kotlin/org/koin/core/KoinApplication.kt#L104...L107

fun main() {
    startKoin {
        environmentProperties()
        modules(listOf(module))
    }
    MainComponent().sayMessage()
}

MainComponentsayMessageを実行するとめでたくHello, World!と表示されると思います。 これで環境変数バンドルするクラスをInjectすることができるようになりました。

また、Koinは環境変数だけではなく、Propertiesファイルの読み込みもサポートしています。 その読み込みに関しても、先程の、getProperty関数でサポートしているため、環境変数とPropertiesファイルの両方を統一的に扱うことができるのもKoinの良いところです。

終わりに

短かったですが、Koinでの環境変数の利用の方法を共有させていただきました。 それでは。