애노테이션이란?
애노테이션 사전적 의미로는 주석이라는 뜻이며 자바에서 사용될 때의 애노테이션은 코드 사이에 주석처럼 쓰여서 특별한 의미, 기능을 수행하도록 하는 기술입니다. 즉, 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta data: 데이터를 위한 데이터)라고 볼 수 있습니다.
다음은 애노테이션의 용도를 나타낸 것입니다.
- 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공
- 소프트웨어 개발툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보 제공
- 실행시(런타임시) 특정 기능을 실행하도록 정보를 제공
기본적으로 애노테이션을 사용하는 순서는 다음과 같습니다.
1. 애노테이션의 정의
2. 클래스에 애노테이션을 배치
3. 코드가 실행되는 중에 Reflection을 이용하여 추가정보를 획득하여 기능 실시
1. 애노테이션의 정의
- 애노테이션을 적용할 때는 애노테이션이 어디에 적용되며 언제까지 애노테이션 소스가 유지될 것인지를 설정하여야 하는데 소스 코드에는 다음과 같이 애노테이션을 정의해 주면 됩니다.
@Target({ElementType.[적용대상]})
@Retention(RetentionPolicy.[정보유지되는 대상])
public @interface [어노테이션명]{
public 타입 elementName() [default 값]
...
}
@Target에는 어떠한 값(ex: 클래스, 필드, 메서드 ...)에 애노테이션을 적용할 것인지를 명시할 수 있으며 아래의 표와 같습니다.
ElementType 열거 상수 | 적용대상 |
TYPE | 클래스, 인터페이스, 열거 타입 |
ANNOTATION_TYPE | 애노테이션 |
FIELD | 필드 |
CONSTRUCTOR | 생성자 |
METHOD | 메서드 |
LOCAL_VARIABLE | 로컬 변수 |
PACKAGE | 패키지 |
@Retention에는 애노테이션 값들을 언제까지 유지할 것인지 값을 입력하는데 각 값이 가지는 의미는 다음 표와 같습니다.
RetentionPolicy 열거 상수 | 설명 |
SOURCE | 소스상에서만 애노테이션 정보를 유지하며 소스 코드를 분석할 때만 의미가 있고, 바이트 코드 파일에는 정보가 남지 않는다. |
CLASS | 바이트 코드 파일까지 애노테이션 정보를 유지하지만 리플렉션을 이용해서 애노테이션 정보를 얻을 수는 없다. |
RUNTIME | 바이트 코드 파일까지 애노테이션 정보를 유지하면서 리플렉션을 이용해서 런타임에 애노테이션 정보를 얻을 수 있다. |
2. 애노테이션의 배치 및 사용
간단한 애노테이션을 생성하여 특정 메서드에 지정 후 테스트 코드를 작성하였습니다.
메서드에서 리플렉션 라이브러리를 사용하여 애노테이션 정보를 가져오는지 확인해봅시다.
SimpleAnnotation.java
- 애노테이션 생성
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleAnnotation {
/**
* default 키워드는 자바 8에서부터 인터페이스에 사용할 수 있도록 도입이 되었고,
* 이 키워드를 사용하면 인터페이스에 추상 메서드가 아닌 구현부를 지닌 메서드를 정의할 수 있다.
*/
String value() default "-";
int number() default 10;
}
SimpleService.java
- 애노테이션을 메서드에 지정합니다.
public class SimpleService {
@SimpleAnnotation(value = "*", number = 15)
public void foo(){
System.out.println("foo");
}
}
SimpleServiceTest.java
- 애노테이션의 정보를 리플렉션 라이브러리를 통해 가져와 예상된 결과를 검증합니다.
import org.junit.jupiter.api.Test;
import parts.rest.annotation.SimpleAnnotation;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class SimpleServiceTest {
/**
* Retention.Runtime으로 지정된 SimpleAnnotation을
* 타겟 메서드 정보를 통해 조회하여 확인하는 학습테스트
*/
@Test
public void check_annotation_on_foo(){
AtomicReference<Method> m = new AtomicReference<>();
assertDoesNotThrow(() -> {
m.set(SimpleService.class.getMethod("foo"));
});
assertTrue(m.get().isAnnotationPresent(SimpleAnnotation.class));
assertEquals(m.get().getName(), "foo");
SimpleAnnotation annotation= m.get().getDeclaredAnnotation(SimpleAnnotation.class);
String value=annotation.value();
int number=annotation.number();
StringBuilder sb = new StringBuilder();
for(int i=0; i<number; i++) sb.append(value);
assertEquals("***************", sb.toString());
}
}
참고
'[개발] 언어 > Java' 카테고리의 다른 글
SOLID (1) | 2023.10.30 |
---|---|
외부 라이브러리의 thread-safety 확인하는 방법 (0) | 2022.03.24 |
JAVA BigDecimal을 왜 그리고 어떻게 사용할까? (0) | 2021.06.23 |
The unknown errors occur in pom.xml when using STS4 (0) | 2019.08.03 |
Apache POI (0) | 2018.01.24 |