Created
February 16, 2023 15:46
-
-
Save stellingsimon/71b48700a0c42852ba51b9f802342406 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.slf4j.Logger | |
import kotlin.properties.ReadOnlyProperty | |
import kotlin.reflect.KClass | |
import kotlin.reflect.KProperty | |
/** | |
* Use as follows: | |
* ``` | |
* class SomeClass { | |
* companion object { | |
* val LOGGER by companionLoggerProvider() | |
* } | |
* } | |
* ``` | |
* | |
* The above is equivalent to | |
* ``` | |
* class SomeClass { | |
* companion object { | |
* val LOGGER: Logger = LoggerFactory.getLogger(SomeClass::class.java) | |
* } | |
* } | |
* ``` | |
* but eliminates the risk of accidentally using some other class inside the `LoggerFactory.getLogger()` call. | |
*/ | |
fun loggerProvider() = LoggerProvider() | |
class LoggerProvider { | |
operator fun provideDelegate(thisRef: Any, prop: KProperty<*>): ReadOnlyProperty<Any, Logger> { | |
val thisKlass = thisRef::class | |
val loggerClazz = when { | |
thisKlass.isCompanion -> thisRef::class.companionedJavaClass() | |
else -> thisRef::class.java | |
} | |
val logger = LoggerFactory.getLogger(loggerClazz) | |
return ReadOnlyProperty<Any, Logger> { _, _ -> logger } | |
} | |
/** | |
* @return the class that contains the companion object | |
*/ | |
private fun KClass<*>.companionedJavaClass(): Class<*> = this.java.declaringClass | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.hamcrest.MatcherAssert.assertThat | |
import org.hamcrest.Matchers.equalTo | |
import org.junit.jupiter.api.Test | |
class LoggerProviderTest { | |
@Test | |
fun `it should use parent class if called from a companion object to log`() { | |
// Act | |
val logger = ExampleClassWithCompanion.LOGGER // accessing the property triggers the property delegate provider | |
// Assert | |
assertThat(logger.name, equalTo(ExampleClassWithCompanion::class.java.name)) | |
} | |
@Test | |
fun `it should use class to log`() { | |
// Act | |
val logger = | |
ExampleClassWithoutCompanion().logger // accessing the property triggers the property delegate provider | |
// Assert | |
assertThat(logger.name, equalTo(ExampleClassWithoutCompanion::class.java.name)) | |
} | |
@Test | |
fun `it should use ExampleObject to log`() { | |
// Act | |
val logger = ExampleObject.logger // accessing the property triggers the property delegate provider | |
// Assert | |
assertThat(logger.name, equalTo(ExampleObject::class.java.name)) | |
} | |
} | |
private class ExampleClassWithCompanion { | |
companion object { | |
val LOGGER by loggerProvider() | |
} | |
} | |
private class ExampleClassWithoutCompanion { | |
val logger by loggerProvider() | |
} | |
private object ExampleObject { | |
val logger by loggerProvider() | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment