【问题标题】:Kotlin extension log function with logback(slf4j)带有 logback(slf4j) 的 Kotlin 扩展日志功能
【发布时间】:2017-10-25 10:47:17
【问题描述】:

我已经为日志创建了一个扩展函数:

import org.slf4j.LoggerFactory

fun Any.log(msg: String) {
    LoggerFactory.getLogger(javaClass.name).debug(msg)
}

但我不确定它是否会在任何时候被调用,因为方法 LoggerFactory.getLogger 正在调用 getILoggerFactory

Mb 有人已经做过类似的事情,可以向我保证不会有任何内存泄漏:) ?

现在我使用老式方法(在类中声明记录器字段):

companion object {
    private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name)
}

但是像这样的简单unit 测试:

@Test
fun testLogger() {
    val start = System.currentTimeMillis()
    for (i in 0..999) {
        log("i=" + i)
    }
    val end = System.currentTimeMillis()
    val time = end - start
    println("*** TIME=" + time.toDouble() / 1000 + " sec")
}

显示与旧时尚选项相同的结果:

@Test
fun testLogger() {
    val start = System.currentTimeMillis()
    for (i in 0..999) {
        logger.debug("i=" + i)
    }
    val end = System.currentTimeMillis()
    val time = end - start
    println("*** TIME=" + time.toDouble() / 1000 + " sec")
}

companion object {
    private val logger = LoggerFactory.getLogger(LoggerTest::class.java.name)
}

~*** TIME=0.02 sec

我正在使用:

org.slf4j - 1.7.25
ch.qos.logback - 1.2.3

【问题讨论】:

  • 似乎LoggerFactory.getLogger(...) 不会每次都构造一个新的记录器并且能够重复使用它们,但是正如this answer 中所说,调用不是免费的,所以你不应该这样做。
  • 也许还有另一个选项可以使用 logback 制作扩展 kotlin 功能?
  • 如果您使用Any.foo() { do sth with javaClass } 并像String.foo() 一样调用它,那么javaClass 应该是StringAny(我不确定),但绝对不是调用类。但是,与老式方式相比,这不会给您相同的结果
  • 实际上我可能会选择interface HasLogger { val logger : Logger } 并定义HasLogger.log()。虽然这仍然需要每个实例一个记录器,而不是每个类一个记录器

标签: kotlin logback slf4j extension-function


【解决方案1】:

对于日志记录,我可以推荐另一种解决方案。

首先,添加接口 ILogging 和类 LoggingImpl:

interface ILogging {
    val log: Logger
}

class LoggingImp(loggerImpl: Logger) : ILogging {
    override val log: Logger = loggerImpl

    companion object {
        operator inline fun <reified T> invoke(): LoggingImp {
            return LoggingImp(LoggerFactory.getLogger(T::class.java))
        }
    }
}

现在您可以使用 Kotlin 委托将记录器添加到任何类:

class TestClass : ILogging by LoggingImp<TestClass>() {
    fun test() {
        log.info("test")
    }
}

创建父对象时会创建记录器。用法示例:

fun main(args: Array<String>) {
    val testClass = TestClass()

    testClass.test()
}

希望,这会对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2021-07-08
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多