[백기선님께서 주최하시는 Java 기초스터디]
github.com/whiteship/live-study
whiteship/live-study
온라인 스터디. Contribute to whiteship/live-study development by creating an account on GitHub.
github.com
12주차 과제의 주제는 애노테이션이다
▶ 애노테이션(Annotation) 이란?
인터페이스의 특별한 종류로 이름에서 유추할 수 있듯이 Java 프로그램의 어떤 부분에 주석을 다는 것을 의미한다
♣ 애노테이션의 사용목적
프로그램에 관해 추가적인 정보를 제공하기 위해 사용된다
♣ 애노테이션의 특징
- 애노테이션은 @ 문자로 시작한다
- 애노테이션은 메타데이터(정보)를 프로그램의 요소인 객체 변수, 생성자, 메소드, 클래스 등등에 연결 짓는 걸 도와준다
- 애노테이션은 순수한 주석이 아니다. 애노테이션은 컴파일러에 의해 프로그램이 처리되는 방식을 변경할 수 있다
▶ 애노테이션을 정의하는 방법
애노테이션을 정의하기 위한 문법은 다음과 같다
[접근 지시자] @interface <애노테이션 이름> {
자료형 <메소드이름>() [default 값];
}
위에서 명시 한 키워드들에 대해 살펴보자
- '애노테이션 이름' 은 이 애노테이션의 식별자이다 이후에 이 이름으로 애노테이션을 사용할 수 있다
- 메소드 선언에서 매개변수를 명시할 수 없고 throws 절과 함께 선언할 수도 없다
- 매개변수는 null 값을 가질 수 없다. 하지만 기본값을 지정하여 선언할 수 있다
- [default 값] 부분은 Optional 이다
- 메소드의 반환 타입은 primitive, enum, String, class 이름 또는 이 타입들의 배열이 될 수 있다
아래서 살펴 볼 @Retention, @Target, @Documented 애노테이션들은 메타 애노테이션이라 불리며 다른 애노테이션에 적용될 애노테이션이라는 의미를 가진다
먼저 @Retention 애노테이션에 대해 살펴볼 것이다
▶ @Retention
이 애노테이션은 애노테이션이 유효한 단계를 명시한다
문법:
@Retention(RetentionPolicy)
RetentionPolicy 에는 아래와 같이 3가지 타입이 존재한다
- RetentionPolicy.SOURCE
애노테이션이 소스레벨에서만 유효하다는 것을 의미한다. 컴파일러에 의해서 이 애노테이션은 무시된다 - RetentionPolicy.CLASS
애노테이션이 컴파일 시에 컴파일러에 의해 유효하며, JVM 에서는 무시된다 - RetentionPolicy.RUNTIME
애노테이션이 실행 시에 JVM 에서 유효함을 의미한다
예제)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
위에서 MyAnnotation 애노테이션은 런타임에 유효하다는 것을 의미한다
※ 만약에 @Retention 애노테이션을 명시하지 않으면 기본 정책은 RetentionPolicy.CLASS 이다
▶ @Target
이 애노테이션을 사용해서 애노테이션이 적용 될 대상을 제한 할 수 있다
문법:
@Target(ElementType)
여기서 ElementType 에는 다음 중 한 가지를 명시할 수 있다
- ANNOTATION_TYPE
- CONSTRUCTOR
- FIELD
- LOCAL_VARIABLE
- METHOD
- PACKAGE
- PARAMETER
- TYPE
타입의 이름을 보면 적용될 대상이 무엇인지 유추할 수 있다
참고로, TYPE 은 모든 ElementType 을 말한다
예제)
@Target(ElementType.METHOD)
public @interface MyAnnotation {}
위 애노테이션은 메소드에만 annotate 될 수 있다
▶ @Documented
기본적으로 커스텀 애노테이션은 공식 자바 문서에 포함되지 않는다
우리가 정의한 애노테이션을 Javadoc 문서에 포함시키기 위해서는 @Documented 애노테이션을 사용하면 된다
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
▶ 애노테이션 프로세서
애노테이션은 두 가지 시점에서 평가된다
◈ 런타임: 애플리케이션이 실행 될 때 Reflection 을 통해서 평가
◈ 컴파일: 자바 컴파일러가 소스코드를 컴파일 할 때
애노테이션 프로세싱은 컴파일 타임에 javac 내에 어노테이션들을 스캔하고 처리하는 하기 위한 빌드 도구이다
애노테이션 프로세서는 Java 5 부터 사용가능 했지만 유용한 API 는 Java 6 부터 지원했다고 한다
특정 애노테이션에 대한 애노테이션 프로세서는 Java 코드 (또는 컴파일 된 바이트 코드) 를 입력으로 사용하고, 생성된 파일 (일반적으로 .java 파일) 을 출력으로 사용한다
즉, 애노테이션 프로세서는 컴파일 된 자바코드를 .java 파일로 생성할 수 있다는 것이다
이게 의미하는 바는 다음과 같다
- 존재하고 있는 클래스에 대한 인스턴스에 메소드를 추가하는 등의 조작은 할 수 없다
- 생성된 자바 파일은 다른 자바 소스 파일에 의해 쓰여진 javac 에 의해서 컴파일 된다
♣ Abstract Processor
모든 프로세서는 AbstrctProcessor 로 부터 확장된다
위에서 필수적으로 구현해야 하는 메소드는 process 메소드이다
◈ 메소드 설명
- init:
모든 애노테이션 프로세서 클래스는 반드시 기본 생성자를 갖는다. 그리고 ProcessingEnvironment 를 매개변수로 갖는 애노테이션 프로세싱 도구에 의해서 실행되는 init() 메소드가 있다. 이 메소드를 통해서 ProcessingEnvironment 변수를 초기화 한다
ProcessingEnvironment 는 인터페이스로 유용한 유틸 클래스인 Elements, Types, Filer, Message 에 관한 정보를 얻기 위한 메소드를 제공한다
- process:
이 메소드는 각 processor 의 메인 메소드 역할을 한다. 이 메소드 내부에 scanning, 평가, 애노테이션에 관한 처리 그리고 java 파일들을 생성하는 작업 등의 코드를 작성한다
RoundEnvironment 를 매개변수로 전달해서 특정 애노테이션에 annotate 된 요소들을 위한 query(질의) 를 할 수 있다
- getSupportedAnnotationTypes():
어노테이션 프로세서가 등록해야 할 어노테이션을 명시한다
중요한 점은 반환 타입이 처리하기 원하는 어노테이션 타입의 이름이 완전히 명시된 문자열의 집합이라는 것이다
즉, 여기서 반환한 애노테이션의 집합은 어노테이션 프로세서에 등록한다는 것
- getSupportedSourceVersion():
Java 의 버전을 명시하는 데에 사용된다. 보통 SourceVersion.latestSupported() 를 반환한다
Java7 부터는 getSupportedAnnotationTypes(), getSupportedSourceVersion() 메소드를 오버라이드 하는 대신에 애노테이션을 통해서 명시해줄 수 있다
[참고자료]
hannesdorfmann.com/annotation-processing/annotationprocessing101/
https://www.baeldung.com/java-annotation-processing-builder
https://www.javacodegeeks.com/2015/09/java-annotation-processors.html
'공부 > whiteship-java' 카테고리의 다른 글
14주차: 제네릭 (0) | 2021.02.27 |
---|---|
13주차: I/O (0) | 2021.02.25 |
11주차: enum (0) | 2021.01.30 |
10주차: 멀티쓰레드 프로그래밍 (0) | 2021.01.22 |
9주차: 예외 처리 (0) | 2021.01.16 |