JAVA/Reflection

애너테이션 with Reflection 1

최-코드 2024. 12. 1. 12:56

애너테이션

  • 자바에서 @를 가진 식별자는 컴파일러가 애너테이션으로 해석한다.
  • 애너테이션은 메서드, 생성자, 필드, 클래스 뿐만 아니라 매개변수, 예외처리, ... 등 코드 내 위치에 나타난다.
  • 애너테이션 자체는 기능이 전혀 없고, 프로그램에 영향을 끼치지 않고, 추가 정보나 에너테이트하는 타깃 관련 메타데이터를 제공하거나 전체 프로그램 관련 정보를 제공하는 자바의 한 방법일 뿐이다.
  • 애너테이션은 JVM에 넣고 reflection을 통해 런타임 동안 그 애너테이션에 접근할 수 있다.
  • 애너테이션은 인자를 가질 수 있다. 예를 들어 spring에서 @Scheduled(initialDelay =1000, fixedRate=60)와 같이 인자값을 전달할 수 있다.
  • 인자를 가지지 않은 애너테이션을 마킹 애너테이션이라고 칭한다.

애너테이션과 리플렉션 간의 관계

  • 애너테이션을 사용하면 Reflection 코드에게 어떤 타깃(애너테이션이 붙은 것)에 가서 무슨 작업을 해야하는지 지시하고 명령할 수 있기에 애너테이션과 reflection은 연관성이 있다.
  • 예1) 다른 애너테이션을 이용해 reflection에게 다른 클래스를 다루고(@Component) 초기화(@Autowired)하는 방법을 알려줄 수 있다.
  • 예2) junit의 경우 테스트 순서(@Before, @After)와 호출시기를 알려주거나 할 수 있다.

애너테이션 선언

  • 애너테이션 선언은 @interface 키워드로 시작한다. 이를 통해 Annotation 인터페이스를 extends한다.
  • 애너테이션 내부의 애너테이션 요소(메소드, 필드)는 인터페이스와 유사하게 선언된다. 이 때 default 키워드로 디폴트 값을 설정할 수 있다. 이는 메소드에도 달 수 있다.
  • 애너테이션 요소의 타입은 모든 원시 자료형, String, Enum, Class<?>, 다른 애너테이션, 앞서 말한 것들의 배열이다.
  • reflection에서 모든 애너테이션을 볼 수 없다. 일반적으로 JVM은 기본값으로 애너테이션을 무시한다.

메타 에너테이션

  • 애너테이션의 가시성과 다른 많은 특성을 제어하기 위해 특별한 애너테이션인 메타 애너테이션이 있다. 메타 애너테이션은 다른 애너테이션에 적용되는 애너테이션이다.
  • 메타 애너테이션 중 가장 중요한 건 Retention 메타 애너테이션이다. 표시된 애너테이션의 저장 기간과 이 저장 상태의 보존 기간을 명시한다.
    • RetensionPolicy.SOURCE로 enum을 설정할시에 컴파일링 이후엔 버릴 애너테이션을 표시하는 것이다. IDE와 컴파일러가 오류나 경고를 보내는 걸 돕고 코드가 컴파일링 된 이후에는 다른 목적을 갖지 않는다. 예를 들어 @Override가 있다.
    • RententionPolicy.CLASS은 컴파일 뒤 클래스 파일에 애너테이션을 저장하도록 컴파일러에게 지시한다. 그러나 JVM이 런타임 동안 애너테이션을 무시한다. JAVA코드를 읽고 분석한 다음 새로운 클래스를 생성하는 코드 생성기가 사용할 수 있다. 그러나 코드 생성 이후 이런 애너테이션은 런타임 동안 더는 목적을 갖지 않는다. 예를들어 @AutoValue가 있다.
    • RententionPolicy.RUNTIME은 컴파일러에게 클래스 파일의 표시된 애너테이션을 기록하게 하고 런타임 동안 JVM이 애너테이션을 이용할 수 있게 한다. reflection을 통해 커스텀 애너테이션을 사용하고 싶을 때 사용할 수 있는 retention 정책이다. 예를 들어 생성한 애너테이션을 런타임 동안 사용 가능하게 표시하려면 reflection을 통해 애너테이션을 찾고 작업해서 보존 정책을 런타임 값으로 선언해 애너테이트 해야 한다.
    • 형식은 @Retention(RetentionPolicy.RUNTIME)와 같다.
@Override 애너테이션을 사용하면 컴파일러가 해당 메서드가 상위 클래스를 오버라이드하는지 확인하고, 상위 클래스의 메서드와 시그니처가 다르면 오류를 발생시킨다. 
@AutoValue 애너테이션은 equals(), hashCode(), toString() 메소드를 자동으로 생성해준다.
  • 다음으로 중요한 메타 애너테이션은 타깃 메타 애너테이션이 있다. 이 애너테이션은 애너테이션이 적용될 수 있는 타깃을 제한한다. 타깃 값은 하나가 되거나 enum 타입 유형으로 사용할 수 있는 요소 유형의 결합이 될 수 있다.
    • 형식은 @Target({ElementType.FIELD, ...})와 같다. 만약 하나이면 중괄호를 빼도 무방하다.