kotlin 通过反射获取注解值

mctunoxg  于 2023-03-30  发布在  Kotlin
关注(0)|答案(2)|浏览(160)

我试图获取注解的所有“Keys”以供以后使用,我像这样初始化值:

private val wgKeys = SpecialRequestContext::class.members.associate { m ->
    m.name to run {
        val headerAnnotation = m.annotations.find { a -> a is Header } as? Header
        headerAnnotation?.key
    }
}

不幸的是,结果是一个Map,其名称为key(正确),但所有值都为null。在调试时,我看到m.annotations没有值。
注解在此步骤中是否不可用?

更新:这里是演示这一点的最小代码,不幸的是Kotlinplayground不能做反射:

@Target(AnnotationTarget.VALUE_PARAMETER)
annotation class Header(val key: String)

data class SpecialRequestContext(
    @Header("BK-Correlation-Id") val correlationId: String? = null,
    @Header("BK-Origin") val origin: String? = null,
    @Header("BK-Origin-City") val originCity: String? = null,
)

fun main() {
    println(wgKeys.count())
    println(wgKeys["origin"])
}

private val wgKeys = SpecialRequestContext::class.members.associate { m ->
        m.name to run {
            val headerAnnotation = m.annotations.find { a -> a is Header } as? Header
            headerAnnotation?.key
        }
    }
vlurs2pr

vlurs2pr1#

注意事项:

@Target(AnnotationTarget.VALUE_PARAMETER)

这意味着注解应用于构造函数的参数,而不是属性,你不会在属性上找到它们。
要在属性中查找它们,可以将其更改为:

@Target(AnnotationTarget.PROPERTY)

如果出于某种原因需要将它们应用于参数,可以像这样找到它们:

private val wgKeys = SpecialRequestContext::class.primaryConstructor!!.parameters.associate { p ->
    p.name to p.findAnnotation<Header>()?.key
}
drkbr07n

drkbr07n2#

我相信有更好的方法来做到这一点,但基本上你需要:
1.获取注解的所有属性
1.对于每个属性,您需要反射性地获取该注解示例的值(这是因为2个不同的类可能具有相同的注解,但值不同)。
一个(粗略的)例子:

annotation class Annotation1(val key1: String, val key2: Int)
annotation class Annotation2(val key3: String, val key4: Int)

@Annotation1(key1 = "value1", key2 = 2)
@Annotation2(key3 = "value3", key4 = 4)
class MyClass

fun main() {
    val myClassAnnotations = MyClass::class.annotations

    val propertiesByAnnotation =
        myClassAnnotations.associateWith { (it.annotationClass as KClass<Annotation>).declaredMemberProperties }

    val keyValuePerAnnotation = propertiesByAnnotation.map { (annotation, properties) ->
        annotation.annotationClass.simpleName!! to properties.map { property ->
            property.name to property.get(annotation)
        }

    }

    println(keyValuePerAnnotation)
}

这将打印一个对列表,其中第一项是注解名称,第二项是每个注解属性的键值对列表。该示例的输出是:

[(Annotation1, [(key1, value1), (key2, 2)]), (Annotation2, [(key3, value3), (key4, 4)])]

相关问题