方便的 Kotlin LoggerFactory 简化
Convenient Kotlin LoggerFactory simplification
在 kotlin 中使用 SLF4J 或其他日志记录方法最方便的方法是什么?
开发人员通常忙于像
这样的样板代码
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
在每个 class 中获得合适的记录器?
使用 Kotlin unify/simplify 最方便的方法是什么?
如果您不喜欢样板文件,您可以随时使用自己的记录器助手包装 log.info
:
mylog.info(this, "data that needs to be logged")
然后在后台,使用某种哈希映射来跟踪 this
参数的 classes,可以为 class 实例化一个记录器。
其他选项可能使用 AspectJ Weaving 将记录器编织到每个 class,但在我看来,这太过分了。
我已经为此定义了一个实用方法
fun getLogger(cl: KClass<*>): Logger {
return LoggerFactory.getLogger(cl.java)!!
}
现在在每个 class 中我都可以像这样使用记录器
companion object {
private val logger = getLogger(MyClass::class)
}
您可以为每种类型定义一个扩展 属性:
val <T : Any> T.logger: Logger
get() = LoggerFactory.getLogger(this::class.java)
使用方法如下:
class X {
init {
logger.debug("init")
}
}
我在我的项目中定义这个函数是为了让我更容易定义记录器。它利用了 Kotlin 的具体化类型。
// Defined in Utilities.kt
inline fun <reified T:Any> logFor() =
LoggerFactory.getLogger(T::class.java)
用法:
class MyClass {
private val log = logFor<MyClass>()
...
}
或者,如果您要创建很多:
class MyClass {
companion object {
private val log = logFor<MyClass>()
}
...
}
这是一个简单示例,其中 returns 来自绑定可调用引用或标准 属性 的延迟初始化记录器。我更喜欢从可调用引用调用,因为 ::
表示反射(与日志记录相关)。
class 提供 Lazy<Logger>
:
class LoggingProvider<T : Any>(val clazz: KClass<T>) {
operator fun provideDelegate(inst: Any?, property: KProperty<*>) =
lazy { LoggerFactory.getLogger(clazz.java) }
}
调用它们的内联函数:
inline fun <reified T : Any> KCallable<T>.logger() =
LoggingProvider(T::class)
inline fun <reified T : Any> T.logger() =
LoggingProvider(T::class)
这是使用它们的示例。初始化程序中的 require
断言表明记录器共享一个引用:
class Foo {
val self: Foo = this
val logger by this.logger()
val callableLogger by this::self.logger()
init {
require(logger === callableLogger)
}
}
在 kotlin 中使用 SLF4J 或其他日志记录方法最方便的方法是什么?
开发人员通常忙于像
这样的样板代码private val logger: Logger = LoggerFactory.getLogger(this::class.java)
在每个 class 中获得合适的记录器?
使用 Kotlin unify/simplify 最方便的方法是什么?
如果您不喜欢样板文件,您可以随时使用自己的记录器助手包装 log.info
:
mylog.info(this, "data that needs to be logged")
然后在后台,使用某种哈希映射来跟踪 this
参数的 classes,可以为 class 实例化一个记录器。
其他选项可能使用 AspectJ Weaving 将记录器编织到每个 class,但在我看来,这太过分了。
我已经为此定义了一个实用方法
fun getLogger(cl: KClass<*>): Logger {
return LoggerFactory.getLogger(cl.java)!!
}
现在在每个 class 中我都可以像这样使用记录器
companion object {
private val logger = getLogger(MyClass::class)
}
您可以为每种类型定义一个扩展 属性:
val <T : Any> T.logger: Logger
get() = LoggerFactory.getLogger(this::class.java)
使用方法如下:
class X {
init {
logger.debug("init")
}
}
我在我的项目中定义这个函数是为了让我更容易定义记录器。它利用了 Kotlin 的具体化类型。
// Defined in Utilities.kt
inline fun <reified T:Any> logFor() =
LoggerFactory.getLogger(T::class.java)
用法:
class MyClass {
private val log = logFor<MyClass>()
...
}
或者,如果您要创建很多:
class MyClass {
companion object {
private val log = logFor<MyClass>()
}
...
}
这是一个简单示例,其中 returns 来自绑定可调用引用或标准 属性 的延迟初始化记录器。我更喜欢从可调用引用调用,因为 ::
表示反射(与日志记录相关)。
class 提供 Lazy<Logger>
:
class LoggingProvider<T : Any>(val clazz: KClass<T>) {
operator fun provideDelegate(inst: Any?, property: KProperty<*>) =
lazy { LoggerFactory.getLogger(clazz.java) }
}
调用它们的内联函数:
inline fun <reified T : Any> KCallable<T>.logger() =
LoggingProvider(T::class)
inline fun <reified T : Any> T.logger() =
LoggingProvider(T::class)
这是使用它们的示例。初始化程序中的 require
断言表明记录器共享一个引用:
class Foo {
val self: Foo = this
val logger by this.logger()
val callableLogger by this::self.logger()
init {
require(logger === callableLogger)
}
}