Чтение аннотаций во время выполнения
Получайте экземпляры аннотаций из объявлений с помощью рефлексии Kotlin.
«Чтение аннотаций во время выполнения» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Предварительные требования
Чтобы читать аннотации во время выполнения, необходимо: (1) объявить аннотацию с помощью @Retention(RUNTIME), (2) добавить зависимость kotlin-reflect в путь к классам и (3) получить ссылку KClass, KFunction или KProperty на аннотированный элемент.
Чтение аннотаций из KClass
Вызовите annotations у KClass, чтобы получить все аннотации этого класса, или используйте findAnnotation для конкретного типа:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Table(val name: String)
@Table(name = "users")
class UserEntity
val ann = UserEntity::class.findAnnotation<Table>()
println(ann?.name) // "users"Чтение аннотаций из свойств
Получайте аннотации свойств через KProperty.annotations или findAnnotation:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)
annotation class Column(val name: String)
data class User(@Column("user_name") val name: String)
val prop = User::name
val col = prop.findAnnotation<Column>()
println(col?.name) // "user_name"Чтение аннотаций из функций
Используйте KFunction.findAnnotation, чтобы прочитать аннотации функций:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class Transactional
class UserService {
@Transactional
fun save(user: User) { /*...*/ }
}
val fn = UserService::save
val isTx = fn.hasAnnotation<Transactional>()
println(isTx) // trueПеребор всех свойств для поиска аннотаций
Распространённый подход — просмотреть все объявленные свойства класса и собрать те, которые помечены определённой аннотацией:
fun <A : Annotation> KClass<*>.annotatedProperties(
annotationClass: KClass<A>
): List<Pair<KProperty1<*, *>, A>> =
declaredMemberProperties
.mapNotNull { prop ->
prop.findAnnotation(annotationClass)?.let { ann -> prop to ann }
}Чтение аннотаций параметров
Получайте аннотации параметров конструктора через KFunction.parameters:
class Repo(
@param:Validate(minLength = 3) val name: String
)
val ctor = Repo::class.primaryConstructor!!
val param = ctor.parameters.first()
val ann = param.findAnnotation<Validate>()
println(ann?.minLength) // 3hasAnnotation и findAnnotation
Используйте hasAnnotation для проверки логического значения, а findAnnotation — когда нужны значения свойств аннотации. Обе являются функциями-расширениями из kotlin.reflect.full.
Обход иерархии классов
Аннотации суперклассов или интерфейсов не наследуются автоматически в рефлексии Kotlin. Если нужны унаследованные аннотации, необходимо обойти KClass.superclasses или использовать KClass.allSuperclasses.
fun KClass<*>.findAnnotationRecursive(ann: KClass<out Annotation>) =
generateSequence(this) { null } // simplified — real impl walks supers
.flatMap { it.annotations }
.firstOrNull { it.annotationClass == ann }Производительность
Вызовы рефлексии медленные. Если вы просматриваете аннотации при запуске фреймворка, кэшируйте результаты в карте с ключами типа KClass. Никогда не читайте аннотации на горячих путях обработки отдельных запросов или кадров.
Цели применения и поля JVM
Для аннотаций свойств с целью @field: аннотация хранится в поле хранения JVM. Получайте её через рефлексию Java (KProperty.javaField?.annotations), а не через список annotations Kotlin, который охватывает только место объявления в Kotlin.
Практический пример: простой сопоставитель ORM
Небольшой сопоставитель ORM читает аннотации @Column, чтобы создать список столбцов SQL:
fun columns(klass: KClass<*>): String =
klass.declaredMemberProperties
.mapNotNull { it.findAnnotation<Column>()?.name }
.joinToString(", ")
println(columns(User::class)) // "user_name, email"Быстрая проверка
Как прочитать из KClass конкретную аннотацию типа MyAnn?
Повторение: чтение аннотаций во время выполнения
Основные выводы:
- Аннотация должна иметь
@Retention(RUNTIME) - Используйте
findAnnotation, чтобы получить значение аннотации, а() hasAnnotation— для логической проверки() - Работает с
KClass,KFunction,KPropertyиKParameter - Кэшируйте результаты просмотра при запуске, чтобы избежать затрат на каждый запрос
- Для аннотаций
@field:используйтеKProperty.javaField
Часто задаваемые вопросы
Урок «Чтение аннотаций во время выполнения» бесплатный?
Да — полный текст урока «Чтение аннотаций во время выполнения» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Чтение аннотаций во время выполнения»?
Получайте экземпляры аннотаций из объявлений с помощью рефлексии Kotlin. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Чтение аннотаций во время выполнения»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Рефлексия Kotlin: KClass, KFunction, KProperty
- Создание и применение пользовательских аннотаций
- Чтение аннотаций во время выполнения
- Валидация и отображение на основе рефлексии