Library에서 Retention 코드를 찾아보면 다음과 같다. 편의상 주석은 제거하였다.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
@Documented - 작성된 Annotation이 Javadoc에 문서화 됨을 표시
@Target - 이 Annotation이 다른 Annotation type에 작성될 수 있음을 표시
Annotation 내부에는 RetentionPolicy라는 Enum 값을 저장할 수 있는 value 속성이 존재한다.
enum RetentionPolicy
RetentionPolicy의 코드는 다음과 같다.
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
설정 가능한 RetentionPolicy 값은 다음과 같다.
SOURCE - 컴파일러에 의해 삭제되는 Annotation
CLASS - 컴파일러에 의해 클래스파일에 기록되지만 런타임 시 VM에서는 관리하지 않음
RUNTIME - 컴파일러에 의해 클래스파일에 기록되고 VM에서 관리하여 실행 중 읽을 수 있음
RetentionPolicy.SOURCE
RetentionPolicy.SOURCE로 설정된 Annotation은 컴파일과 동시에 사라진다. 따라서 다음 용도로 사용이 가능하다.
해당 내용들을 직접 적용하려면 annotation processor 등의 처리가 필요하다.
RetentionPolicy.CLASS
RetentionPolicy.CLASS로 설정된 Annotation은 컴파일 이후의 바이트 코드까지 유지되지만 런타임 시점까지 반드시 유지할 필요는 없다. 따라서 RetentionPolicy.SOURCE와 RetentionPolicy.RUNTIME의 중간 정도로 이해할 수 있다. 보기에 따라서 상당히 애매해 보일 수 있지만 자바 애플리케이션을 만들 때 다수의 jar 파일을 사용하고, 이 jar 파일에는 class 파일만 들어있다는 것을 생각해보면 배포된 파일에는 포함되어야 하지만 실행 시에는 포함될 필요가 없는 경우 사용하는 형태라고 볼 수 있다.
RetentionPolicy.RUNTIME
RetentionPolicy.RUNTIME으로 설정된 Annotation은 VM에서 런타임 시점까지 유지한다. 런타임 시점까지 유지된다는 것은 코드를 통해 Annotation의 유무와 내부에 설정된 옵션을 읽을 수 있다는 의미이다. Java Reflection과 같은 기술을 사용하여 Annotation을 해석하고, 이에 따라 다른 작업을 수행할 수 있다.
다음 Book 클래스를 통해 좀 더 자세히 살펴본다.
Book.java
package com.hacademy.annotation;
@TestEntity(author = "hacdemy", date = "2022-03-03", comment = "테스트를 위한 Annotation")
public class Item {
private String name;
private int price;
public void setName(String name) {
this.name = name;
}
public void setPrice(int price) {
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
@Override
public String toString() {
return "Item [name=" + name + ", price=" + price + "]";
}
}
Book 클래스에는 @TestEntity 라는 Annotation이 설정되어 있다. @TestEntity의 코드는 다음과 같다.