0

I am very new to Kotlin development and I came across custom annotation classes in the documentation.

Is there a way for me to use an annotation on a function as a way to pre-populate some variables, or to run a decorator function before running the annotated function?

Something like:

class TestClass {

    @Friendly("Hello World")
    private fun testFun() {
        greet()
        //does something else
    }
}

with an annotation class like

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
annotation class Friendly(val message: String) {
    fun greet() {
        println(message)
    }
}

I know this isn't valid Kotlin code, but I can't find any examples on how to actually use values from annotations without using reflection (if it's even possible)

Please let me know if I can do something like this, and more usefully, a better resource on annotation classes for Kotlin?

Justin Gilman
  • 479
  • 4
  • 12

1 Answers1

1

To make use of your custom annotations, you need to either create your own annotation processor (and use kapt Kotlin compiler plugin) to generate some new sources (but not modify existing!) at compile time, or use @Retention(AnnotationRetention.RUNTIME) meta-annotation (which is default in Kotlin), so that they could be accessed via reflection in runtime.

@Retention(AnnotationRetention.BINARY) meta-annotation you're using is equivalent of @Retention(RetentionPolicy.CLASS) in java, which is mostly useless (see https://stackoverflow.com/a/5971247/13968673).

What you're trying to do with annotations (call some additional code before/after method execution) reminds me aspect-oriented programming. Take a look at Spring AOP and AspectJ frameworks, following this paradigm, and their approach for annotations processing. TL;DR: Spring AOP is processing annotations in runtime, generating proxy-classes with respectful code, while AspectJ is using its own compiler (even not an annotation processor, cause it also introduces its own syntactic extension for java language), and can generate respectful bytecode at compile-time. They both are originally java-oriented, but with some configurational pain could be used with Kotlin too.