목표
자바의 애노테이션에 대해 학습하세요.
학습할 것 (필수)
- 애노테이션 정의하는 방법
- @retention
- @target
- @documented
- 애노테이션 프로세서
애노테이션이란?
- 사전적 의미로 주석을 의미하며 프로그램에 대한 데이터를 제공하는 메타데이터의 한 형태이다.
- 용도
- 컴파일러에 제공하는 정보 → 컴파일러는 에노테이션을 사용하여 에러를 체크하거나 에러메시지를 억제할 수 있다. ex) @Override
- 컴파일러 시간 및 배포시간 처리 → 소프트웨어 개발툴이 애노테이션 정보를 처리하여 코드, xml 파일 등을 생성할 수 있다. ex) @Getter, Setter
- 런타임 처리 → 일부 애노테이션은 런타임에 특정 기능을 실행하도록 정보를 제공한다.
1. 애노테이션 정의하는 방법
Single-Value Annotation
단일 변수만을 갖는 에노테이션을 말하며, 값을 명시하여 데이터를 전달할 수 있다.
@SuppressWarnings, @Retention, @Target 등
Full Annotation
두 개 이상의 변수를 갖는 에노테이션으로 여러 데이터를 ","를 기준으로 Key : Value 형식으로 전달하게 된다.
@Generated 등
Marker Annotation과 Interface
구현할 메서드, 상수 필드가 존재하지 않는 Interface나 필드 변수가 본재하지 않는 Annotation을 명칭하며 컴파일러, 인터럼터, JVM에게 어떠한 정보를 제공하는 용도로만 사용된다.
Cloneable, Serializable, Remote Interface, @Overide, @Native 등
종류
Compile Time에 정보를 제공하는 Annotation
-
@Override
-
상위 클래스의 메서드를 재정의하였음을 나타내는 Annotation이다. 상위 클래스에 해당 메서드가 존재하지 않을 경우 Compiler가 경고하는 기능을 제공한다.
-
-
@SuppressWarnings
-
컴파일러가 경고하는 내용을 Ignore할 때 사용하는 Annotation이다.
-
-
@Native
-
Native Code에 의해 참조되는 상수 필드에 적용하는 Annotation으로 JNI를 통해 Nataive Method가 호출된다.
-
-
@Generated
-
소스 코드를 생성하는 도구에 의해서 해당 코드가 자동적으로 생성되었음을 나타내는 Annotation이다.
-
Load-Build Time에 정보를 제공하는 Annotation
-
@Nullable
-
parameter에 대해 Null을 허용함을 나타내는 Annotation이다.
-
Runtime Time에 정보를 제공하는 Annotation
-
@FunctionalInterface
-
JDK 8부터 추가된 Annotation으로 해당 Interface가 하나의 메서드만을 제공하는 함수형 인터페이스임을 나타내는 Annotation이다.
-
-
@Deprecated
-
더 이상 지원하지 않는 기능임을 알려준다.
-
-
@SafeVarargs
-
Generic과 같은 가변 인자 Parameter를 사용할 때 발생하는 경고를 Ignore한다.
-
-
@Repeatable
-
해당 Annotation을 반복적으로 사용할 수 있게 지원한다.
-
-
@Inherited
-
Meta Annotation 중 하나로써 적용된 대상 Annotation을 하위 Class, Interface에게 상속시킨다.
-
-
@Retention, @Target, @Documented 등
Custom Annotation 정의
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface SampleAnnotation {
String name() default "";
}
2. @retention
에노테이션이 유지되는 기간을 지정하는데 사용합니다. 어느 시점까지 에노테이션의 메모리를 가져갈지 설정합니다.
종류
- SOURCE
- 애노테이션을 사실상 주석처럼 사용한다고 보면 됩니다 컴파일러가 컴파일 할 때 해당 애노테이션의 메모리는 버린다.
- '@Override'나 '@SuppressWarnings' 처럼 컴파일러가 사용하는 애노테이션은 유지 정책이 'SOURCE' 입니다. 컴파일러를 직접 만드는게 아니라면 주석처럼 사용된다.
- CLASS (default)
- 컴파일러가 컴파일 시에는 애노테이션의 메모리를 가져가지만, 실질적으로 런타임시에는 사라지게 됩니다. 런타임시에 사라진다는 것은 리플렉션으로 선언된 애노테이션 데이터를 가져올 수 없게 됩니다. 즉, 실행 타임에서 애노테이션에 대한 데이터를 활용할 수 없다는것을 의미합니다.
- 예를들어 해당 클래스에 있는 애노테이션의 정보를 가져오고 싶을 때 유지정책이 SOURCE나 CLASS 라면 가져오는것이 불가능합니다. (런타임시에 이미 애노테이션에 대한 메모리가 없기 때문에)
- RUNTIME
- 애노테이션을 런타임시에까지 사용할 수 있습니다. JVM이 자바 바이트코드가 담긴 class 파일에서 런타임 환경을 구성하고 런타임을 종료할 때까지 메모리는 살아있습니다.
3. @target
Meta Annotation 중 하나로써 적용된 대상 Annotation이 어느 위치에 적용될 수 있는지 정의하는 Annotation이다.
ElementType 필드 변수
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
4. 애노테이션 프로세서
Compile 시점에서 정의된 Annotation을 분석하고 처리하기 위해 사용되는 API이다.
소스 코드를 구문 분석하여 나타나는 결과인 Abstract Syntax Tree를 조작하여 코드를 추가하거나, 설정 정보를 변경하거나, 컴파일 에러, 경고 등을 생성하기도 한다.
컴파일 시점에 조작하기 때문에 런타임 비용이 없다.
대표적인 예제
- 롬복(Lombok)
- @Getter, @Setter, @Builder
- AutoService
- 리소스 파일을 만들어줍니다.
- META-INF 밑의 service밑에 SeviceLoader용 레지스트리 파일을 만들어줍니다.
- @Override
- 컴파일러가 오버라이딩하는 메서드가 잘못된 대상임을 체크해주는것도 에노테이션 프로세서
- Dagger2
- 컴파일 타입 DI 제공 → 런타임 비용이 없어진다.
Annotation Processing Flow
- 자바 컴파일러에 의해 빌드
- Annotation Processor들이 각각의 처리 시작
- 주석이 달린 Class, Method, Field를 찾는다.
- 발견된 부분들의 정보를 이용하여 코드를 생성, 검증 (Lombok 등의 코드 생성 시점)
- 생성된 정보, 코드, 문자열 등을 class로 작성한다.
- 컴파일러가 모든 Processor가 실행되었는지 확인 후, 다음 Round를 진행하거나 실행 종료한다.
'Language > Java' 카테고리의 다른 글
자바 11주차 : Enum (0) | 2021.03.05 |
---|---|
자바 10주차 : 멀티쓰레드 프로그래밍 (0) | 2021.03.05 |
자바 9주차 : 예외 처리 (0) | 2021.02.14 |
JAVA 8주차 : 인터페이스 (0) | 2021.02.14 |
JAVA 7주차 : 패키지 (0) | 2021.02.14 |
댓글