Каков идиоматический способ Kotlin приобрести Logger?

Я ищу заменить

private static final Logger log = Logger.getLogger(MyClass.class);

с чем-то немного менее многословным и более идиоматическим, то

class MyClass {
    companion object {
        val log = LoggerFactory.getLogger(MyClass::class.java)
    }

    fun usage() {
        log.debug("Success")
    }
}

Бонусные баллы за то, что вам не нужно заботиться об этом в каждом классе.

Я старался:

interface HasLogger {
    val log: Logger
        get() = LoggerFactory.getLogger(this.javaClass)
}

Но это приводит к тому, что вызов getLogger() для каждого использования (недопустимо) также возвращает регистратор для подтипа (а не того, где он был объявлен).

2 ответа

Решение

Вы можете создать служебный метод, как

inline fun <reified T:Any> loggerFor() = LoggerFactory.getLogger(T::class.java)

И просто используйте это как

class MyClass {
    companion object {
        val log = loggerFor<MyClass>()
    }

    fun usage() {
        log.debug("Success")
    }
}

В качестве альтернативы вы могли бы использовать личный регистратор на уровне файлов, который сэкономит вам некоторую печатность, что кажется хорошим решением, когда у вас нет нескольких классов с их собственными регистраторами, определенными для файла:

private val log = loggerFor<MyClass>()

class MyClass {
    fun usage() {
        log.debug("Success")
    }
}

Во-первых, вы можете добавить функции расширения для создания регистратора.

inline fun <reified T : Any> getLogger() = LoggerFactory.getLogger(T::class.java)
fun <T : Any> T.getLogger() = LoggerFactory.getLogger(javaClass)

Тогда вы сможете создать регистратор, используя следующий код.

private val logger1 = getLogger<SomeClass>()
private val logger2 = getLogger()

Во-вторых, вы можете определить интерфейс, который обеспечивает регистратор и его смешанную реализацию.

interface LoggerAware {
  val logger: Logger
}

class LoggerAwareMixin(containerClass: Class<*>) : LoggerAware {
  override val logger: Logger = LoggerFactory.getLogger(containerClass)
}

inline fun <reified T : Any> loggerAware() = LoggerAwareMixin(T::class.java)

Этот интерфейс может быть использован следующим образом.

class SomeClass : LoggerAware by loggerAware<SomeClass>() {
  // Now you can use a logger here.
}
Другие вопросы по тегам