본문 바로가기
기타/자바 중급

자바 어노테이션(2) - 리플렉션

by 창이2 2021. 6. 23.

안녕하세요.

이번 포스팅에서는 어노테이션이 리플렉션을 통해

어떻게 사용될 수 있는지 적어보려고 합니다.

 

리플렉션이란 클래스의 정보를 알아내는 것인데 동적으로

클래스 정보를 얻을 수 있는 프로그래밍 방법입니다.

클래스만 알고 있다면 해당 클래스의 변수나 메소드 등을 알 수 있습니다.

 

이 리플렉션을  통해 클래스에 어떤 어노테이션이 적용 되었고

해당 어노테이션에 대한 정보 또한 알 수 있습니다.

 

코드는 코틀린 기준으로 작성되었으며 이를 기준으로 설명드리겠습니다.

일단 프로젝트에 코틀린에서 리플렉션을 사용하기 위한 라이브러리를 설치합니다.

    implementation "org.jetbrains.kotlin:kotlin-reflect:1.5.20"

 

 

어노테이션과 이를 적용할 data class를 선언하겠습니다.

 

@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) //AnnotationRetention.SOURCE => null
@Target(
    AnnotationTarget.PROPERTY
)
annotation class MyIntRange(
    val from: Int,
    val to: Int
)

data class ReflectionData(
    @MyIntRange(1000, 10000)
    val bbb: Int,

    @MyIntRange(10, 20)
    val ccc: Int,

    @MyIntRange(1, 100)
    val aaa: Int

)

MyIntRange라는 어노테이션을 만들었는데 

이전 포스팅에서 설명 드렸던 타겟과 리텐션을 정의한 것을 알 수 있습니다.

https://dog-footprint.tistory.com/42

 

자바 어노테이션(1)

안녕하세요. 이번 포스팅에서는 자바에서 사용되는 어노테이션에 대해 알아 보겠습니다. 1. 어노테이션 정의 어노테이션을 정의 할때 고려할 것은 크게 2가지로 볼수 있습니다. 첫번째는 어떤

dog-footprint.tistory.com

 

 

 

이제 어노테이션이 적용된 데이터클래스를 작성하였다면

이를 런타임에 어떻게 처리할 수 있는지에 대한 코드를 작성해보겠습니다.

 

fun validate(data: ReflectionData){
    data::class.declaredMemberProperties.forEach { it->
        val myAnnotation = it.findAnnotation<MyIntRange>()

        if(myAnnotation!=null){
            val value = it.getter.call(data) as Int
            println("${it.javaField?.name} : ${myAnnotation}")
            println("value  : ${value}, from : ${myAnnotation.from}, to : ${myAnnotation.to}")
        }
        println()
    }
}

 

 

declaredMemberProperties라는 코틀린 리플렉션 메소드를 사용해서 

ReflectionData에 있는 프로퍼티 정보들을 가져 옵니다.

 

이후 

findAnnotation<MyIntRange>() 을 이용해 @MyIntRange 이 붙은 프로퍼티를 찾고

해당 어노테이션이 붙은 정보를 출력하게 했습니다.

 

fun main(){
    val data = ReflectionData(10000, 10,100)
    validate(data)
}

메인 함수를 실행하면 아래와 같이 어노테이션과 프로퍼티에 대한 정보를 볼 수 있습니다.

 

aaa : @MyIntRange(from=1, to=100)
value  : 100, from : 1, to : 100

bbb : @MyIntRange(from=1000, to=10000)
value  : 10000, from : 1000, to : 10000

ccc : @MyIntRange(from=10, to=20)
value  : 10, from : 10, to : 20

 

 

그러나 이 리플렉션을 이용하는 것은 런타임에 매번 동작하기 때문에 부담이커 이 방법이 아닌 다른 방법으로

어노테이션을 다루는 경우가 많습니다.

Code Generator를 활용하는 것인데 이것은 다음 포스팅에서 진행하겠습니다.

감사합니다.

 

전체코드

더보기

import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.javaField

fun main(){
val data = ReflectionData(10000, 10,100)
validate(data)
}

fun validate(data: ReflectionData){
data::class.declaredMemberProperties.forEach { it->
val myAnnotation = it.findAnnotation<MyIntRange>()
if(myAnnotation!=null){
val value = it.getter.call(data) as Int
println("${it.javaField?.name} : ${myAnnotation}")
println("value : ${value}, from : ${myAnnotation.from}, to : ${myAnnotation.to}")
}
println()
}
}

data class ReflectionData(
@MyIntRange(1000, 10000)
val bbb: Int,

@MyIntRange(10, 20)
val ccc: Int,

@MyIntRange(1, 100)
val aaa: Int

)

@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) //AnnotationRetention.SOURCE => null
@Target(
AnnotationTarget.PROPERTY
)
annotation class MyIntRange(
val from: Int,
val to: Int
)

'기타 > 자바 중급' 카테고리의 다른 글

자바 어노테이션(1)  (0) 2021.06.18

댓글