어노테이션은 interface 선언에 @를 추가하는 방식으로 선언할 수 있다.
public @interface Annotation{
...
}
어노테이션은 컴파일 또는 런타임시에 참조되어 동작하는데, 이를 정할 수 있도록 Java에서 @Retention 어노테이션으로 제공한다.
@Retention(RetentionPolicy.RUNTIME) // 해당 어노테이션은 런타임까지 존재
@Retention(RetentionPolicy.CLASS) // 해당 어노테이션은 컴파일까지 존재
@Retention(RetentionPolicy.SOURCE) // 해당 어노테이션은 소스코드까지 존재
public @interface Annotation{
...
}
실제로 컴파일이 완료된 .class를 열어보면 RUNTIME policy와 CLASS policy는 존재하는것을 볼 수 있다. RUNTIME policy의 어노테이션은 런타임 시 어노테이션 데이터를 읽어들일 수 있어 Reflection API와 함께 자주 사용된다.
어노테이션을 선언했다면, 이 어노테이션이 참조되는 위치를 정해주어야 한다. 보통 선언 시 어노테이션을 참조해야 하며, 이를 정할 수 있도록 Java에서 @Target 어노테이션으로 제공한다. 사용 예로, 어노테이션이 적용된 클래스에서 멤버변수에 어노테이션을 적용할 것인지, 클래스 내 메소드에 적용할 것인지 결정을 할 수 있다.
@Target(ElementType.TYPE) // 해당 어노테이션을 타입 선언시 적용
@Target(ElementType.FIELD, ElementType.METHOD) // 해당 어노테이션을 멤버 변수와 메서드 선언시 적용
public @interface Annotation{
...
}
// 아주 다양한 선택지가 있다.
// ElementType.PACKAGE : 패키지 선언
// ElementType.TYPE : 타입 선언
// ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
// ElementType.CONSTRUCTOR : 생성자 선언
// ElementType.FIELD : 멤버 변수 선언
// ElementType.LOCAL_VARIABLE : 지역 변수 선언
// ElementType.METHOD : 메서드 선언
// ElementType.PARAMETER : 전달인자 선언
// ElementType.TYPE_PARAMETER : 전달인자 타입 선언
// ElementType.TYPE_USE : 타입 선언
이렇게 생성된 어노테이션은 @Target으로 지정한 타깃들에 대해 다음과 같이 쓰일 수 있다.
RetentionPolicy.SOURCE: 컴파일 단계에서 바이트코드 형태로 Injection되어 사라지거나
RetentionPolicy.CLASS: 외부 라이브러리(.jar 파일은 소스코드가 없이 컴파일이 완료된 .class 바이트코드가 들어있다.) 객체의 타입체킹(@Nonnull) 또는 클래스를 initialize 해주는 Class.forName()의 정상적 동작을 위해 클래스의 이름을 바꿀 수 없도록(@KeepName)하거나
RetentionPolicy.RUNTIME: Reflection API와 함꼐 IoC를 위한 컴포넌트 스캔의 참조로 사용된다.
예로, 다양한 어노테이션을 지원하는 롬복은 SOURCE 정책의 어노테이션이 많은데
롬복은 Java에서 지원하는 Annotation Processing API를 통해
소스코드 파싱 시 생성되는 AST 트리를 수정하여 바이트코드를 Inject한다.
'Today I Learned > Spring Boot' 카테고리의 다른 글
Validation with Advice (0) | 2022.04.25 |
---|---|
Validation 체크 (0) | 2022.04.25 |
Reflection 소개 (0) | 2022.04.24 |
시큐리티 기본 Authentication (0) | 2022.04.24 |
OSIV (0) | 2022.04.24 |