search
LoginSignup
9

More than 5 years have passed since last update.

posted at

KotlinでLoggerの生成を少し楽にした

logger使ってますか?
Log4jとかlog4j2とかslf4jとか 色々なloggerがあると思います。
javaだったらlombockのアノテーションでいい感じにloggerを注入してくれて便利ですが、kotlinでlombockを使っても、イマイチ捗りません。

だからといって下記のようにjavaのコードを素直にkotlinに書き換える感じもめんどくさいです。特に自分で生成したクラスをいちいちLoggerに渡さないといけないなんて面倒極まりない。
ということでkotlinならどう書いたら面倒が少ないのか考えてみました。
なお利用しているloggerはlog4j2ということにしてあります。但し、ちょっと書き換えれば他のloggerでも利用可能です。

java
class LogExample{
    private static final Logger log = LogManager.getLogger(LogExample.class);
}
kotlin
class LogExample(){
    companion object{
        private val log = LogManager.getLogger(LogExample::class.java)
    }
}

1.companion objectに継承

以下のうようにKtLogというクラスを作ります。(クラス名はなんでもいいです。)

KtLog.kt
open class KtLog(){
    var log:Logger = LogManager.getLogger(
        this.javaClass.name.let {
            val matchIndex = it.length - 10
            when (it.lastIndexOf("\$Companion")) {
                matchIndex -> it.substring(0, matchIndex)
                else -> it
            }
        }
    )
}

使うときはcompanion object:KtLog()のようにcompanion objectに継承します。

kotlin
class LogExample(){
    companion object:KtLog()

    fun nanika(){
        log.debug("なにか")
    }
}

デメリットとしてはcompanion objectに他のクラスを継承させることが不可能なことです。
またKtLogではthis.javaClassLogExample$Companionとなる為、クラス名を戻す処理をしています。

2.byを使う

こちらもKtLogの様なクラスを作成します。(クラス名はなんでもいいです。)

KtLog.kt
class KtLog {
    var log:Logger? = null

    operator fun getValue(thisRef:Any,property: KProperty<*>):Logger{
        return log?:LogManager.getLogger(thisRef.javaClass.name.let {
                    val matchIndex = it.length - 10
                    when (it.lastIndexOf("\$Companion")) {
                        matchIndex -> it.substring(0, matchIndex)
                        else -> it
                    }
                }).apply { this@KtLog.log = this }
    }
}

使うときはcompanion object内でprivate val log by KtLog()を記述するだけです。

kotlin
class LogExample(){
    companion object{
        private val log by KtLog()
    }

    fun nanika(){
        log.debug("なにか")
    }
}

なお、companion object内に記述しなくてもOKですが、生成したオブジェクト毎にloggerが生成されてしまいます。パフォーマンスを気にしないのであればこれでも構いません。

kotlin
class LogExample(){
    private val log by KtLog()

    fun nanika(){
        log.debug("なにか")
    }
}

メリットとしては1の方法と違いcompanion objectは継承可能である点と、logの変数を自由に変更できる点です。

結論

おそらく2のほうが使い勝手はいいと思います。
ただ欲を言えばアノテーションを書くだけで注入してほしい・・・。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
9