학습할 것
- 어노테이션 정의하는 방법
- @retention
- @target
- @documented
- 어노테이션 프로세서
먼저 알고가기
어노테이션이란?
- 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것
- 메타데이터. 어플리케이션이 처리하는 데이터가 아닌 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지를 알려주는 정보
어노테이션의 용도
- 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공
소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보를 제공
- 실행 시(런타임 시)특정 기능을 실행하도록 정보를 제공
특징
- 주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다.
- 예를 들어, 소스코드 중 특정 메서드만 테스트하길 원할 경우, 해당 코드에 '@Test' 라는 어노테이션을 붙이면 테스트 프로그램에게 해당 메서드는 테스트를 해야한다는 것을 알릴 뿐 메서드가 포함된 전체 프로그램 자체에는 해당 어노테이션이 아무런 영향을 미치지 않는다.
- JDK에서 제공하는 표준 어노테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공
- 새로운 어노테이션을 정의할 때 사용하는 메타 어노테이션도 제공
어노테이션의 종류
- Built-in Annotation : 자바에서 기본적으로 제공하는 어노테이션
- Meta Annotation : 커스텀 어노테이션을 만들수 있게 제공된 어노테이션.
- Custome Annotation : 사용자가 직접 정의한 어노테이션
1. Built-in Annotation
2. Meta Annotation
어노테이션을 정의하는 방법
- 인터페이스를 정의하는 것과 유사하게 다음과 같이 @interface를 사용해서 정의한다.
public @interface AnnotaionName{
}
- 엘리먼트(element)를 멤버로 가질 수 있다.
public @interface AnnotationName {
String elementName1(); #=> 값이 없으므로 반드시 값을 기술해야 함
int elementName2() default 5; #=> 디폴트 값이 있으므로 생략 가능
}
<위의 어노테이션을 사용할 때>
@AnnotationName(elementName1 = "값", elementName2 = 3);
또는
@AnnotationName(elementName1 = "값");
<기본 엘리먼트가 포함된 어노테이션 선언>
public @interface AnnotationName {
String value(); #=> 기본 element 선언
int elementName() default 5;
}
<Value 엘리먼트를 가진 어노테이션을 적용하는 방법>
@AnnotationName("값"); #=> value자리에 값이 설정되는 것
#value엘리먼트와 다른 엘리먼트의 값을 동시에 주고싶다면
@AnnotationName(value = "값", elementName=3);
- 메타 어노테이션을 사용하여 어노테이션이 적용되는 대상이나 유지기간 등을 지정한다.
- '@'를 이용하여 선언한다.
메타 어노테이션이란?
- 어노테이션을 위한 어노테이션
- 어노테이션에 붙이는 어노테이션
어노테이션 | 설명 |
---|
@Target | 어노테이션이 적용가능한 대상을 지정하는데 사용한다. |
@Documented | 어노테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다. |
@Inherited | 어노테이션이 자손 클래스에 상속되도록 한다. |
@Retention | 어노테이션이 유지되는 범위를 지정하는데 사용한다. |
@Repeatable | 어노테이션을 반복해서 적용할 수 있게 한다. (JDK 1.8) |
@Retention
- 어노테이션이 유지되는 기간을 지정하는데 사용된다.
<어노테이션의 유지 정책>
유지 정책 | 의미 |
---|
SOURCE | 소스 파일에만 존재. 클래스파일에는 존재하지 않음. |
CLASS | 클래스 파일에 존재. 실행시에 사용불가. 기본값 |
RUNTIME | 클래스 파일에 존재. 실행시에 사용가능. |
- SOURCE : 컴파일러가 사용하는 어노테이션. 컴파일러를 직접 작성할 것이 아니면 해당 유지정책은 필요 없다.
- RUNTIME : 실행 시에 리플렉션(reflection)을 통해 클래스 파일에 저장된 어노테이션의 정보를 읽어서 처리할 수 있다.
*Reflection : 런타임 시에 클래스의 메타 정보를 얻는 기능. 클래스의 필드가 무엇인지 어떤 생성자를 가지고 있는지 어떤 메소드를 가지고 있는지 적용된 어노테이션이 무엇인지를 알아내는 것.
=> 런타임 시에 어노테이션 정보를 얻으려면 어노테이션 유지 정책을 RUNTIME으로 해야 한다.
- CLASS : 컴파일러가 어노테이션의 정보를 클래스 파일에 저장할 수 있게는 하지만 클래스 파일이 JVM에 로딩될 때에는 어노테이션의 정보가 무시되어 실행 시에 어노테이션에 대한 정보를 얻을 수 없다.
@Target
- 어노테이션이 적용가능한 대상을 지정하는데 사용된다.
<@SuppressWarnings 어노테이션을 정의하는 예>
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
- '@Target'으로 지정할 수 있는 어노테이션 적용대상의 종류
대상 타입 | 의미 |
---|
ANNOTATION_TYPE | 어노테이션 |
CONSTRUCTOR | 생성자 |
FIELD | 필드(멤버변수, ENUM상수) |
LOCAL_VARIABLE | 지역변수 |
METHOD | 메서드 |
PACKAGE | 패키지 |
PARAMETER | 매개변수 |
TYPE | 타입(클래스, 인터페이스, ENUM) |
TYPE_PARAMETER | 타입 매개변수(JDK 1.8) |
TYPE_USE | 타입이 사용되는 모든 곳(JDK 1.8) |
- TYPE : 타입을 선언할 때 어노테이션을 붙일 수 있다는 뜻
- TYPE_USE : 해당 타입의 변수를 선언할 때 붙일 수 있다는 뜻
@Documented
- 어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.
- 자바에서 제공하는 기본 어노테이션 중에 '@Override', '@SuppressWarnings'를 제외하고는 모두 이 메타 어노테이션이 붙어 있다.
위의 세가지 어노테이션이 적용된 코드의 예시
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
어노테이션 프로세서
- 컴파일 타임에 어노테이션을 분석하는 단계.
- 어노테이션을 이용하여 새로운 리소스르 생성해낼 수 있는 방법 및 과정
프로세싱 과정
- 어노테이션 클래스를 생성한다.
- 어노테이션 파서 클래스(Annotation Parser Class)를 생성한다.
- 어노테이션을 사용한다.
- 컴파일하면, 어노테이션 파서가 어노테이션을 처리한다.
- 자동 생성된 클래스가 빌드 폴더에 추가된다.