Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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のほうが使い勝手はいいと思います。
ただ欲を言えばアノテーションを書くだけで注入してほしい・・・。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした