보통사람

[Study-12주차] 어노테이션(Annotation) 본문

Study

[Study-12주차] 어노테이션(Annotation)

pej4303 2021. 1. 31. 22:46
  • 목표

    • 자바의 어노테이션에 대해 학습하세요.

  • 학습할 것 (필수)

    • 어노테이션 정의하는 방법

    • @retention

    • @target

    • @documented

    • 어노테이션 프로세서

 

1. 어노테이션(Annotation)

  • 소스 코드 안에 추가하여 사용 할 수 있는 메타데이터의 일종

  • 주석처럼 프로그램에는 영향을 주지 않으며 프로그램에 유용한 정보를 제공할 수 있음

  • 용도

    • 컴파일시 어노테이션을 사용하여 오류 및 경고를 알려 줄 수 있음

    • 어노테이션 정보를 이용하여 코드, XML 파일 등을 생성할 수 있음

  • 정의하는 방법

    • @interface 키워드를 이용

접근제어자 @interface 어노테이션명 {
    // 내용 기입
}


public @interface MyAnnotation {
    // 내용 기입
}
  • 어노테이션의 기본 구조

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD })
public @interface MyAnnotation {
    // 기본형 타입 및 String, 배열로 선언 할 수 있음
    int version();
    boolean flag();
    String name();
    String[] typeArr();

    // enum으로도 선언 할 수 있음
    public enum Season {
        SPRING, SUMMBER, FALL, WINTER
    }
    // 기본값도 지정 할 수 있음
    Season season() default Season.WINTER;
}
@MyAnnotation(name = "pej", typeArr = { "A", "B" }, flag = false, version = 0)
public void test() {
}

 

2. 메타 어노테이션

  • 어노테이션을 위한 어노테이션으로 java.lang.annotation에 정의되어 있음

  • 어노테이션에 붙이는 어노테이션

출처 - Java의 정석

 

2.1. @Retention

 

@Retention(유지되는 범위)


@Retention(RetentionPolicy.SOURCE)
  • RetentionPolicy.SOURCE

    • 소스 파일(*.java)에서만 유지됨

  • RetentionPolicy.CLASS

    • 컴파일 시 컴파일러에 의해 유지되며 JVM에서는 무시됨

    • 클래스 파일(*. class)에 있으나 런타임 시 사용할 수 없음

  • RetentionPolicy.RUNTIME

    • 클래스파일(*.class)에 있으나 런타임 시에만 사용할 수 있으며 JVM에 의해 유지됨

    • 런타임 시에 리플렉션(reflection)을 이용해 클래스 파일에 저장된 어노테이션 정보를 읽어서 처리할 수 있음

 

2.2. @Documented

 

  • @Override, @SuppressWarnings 을 빼고 기본적으로 어노테이션은 Javadoc에 포함되지 않음

 

2.3. @Target

 

@Target({적용가능한 대상})


@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})

출처 - https://docs.oracle.com/javase/tutorial/java/annotations/predefined.html

 

 

3. 어노테이션 프로세서(Annotation Processing)

 

  • 컴파일시 어노테이션을 찾아서 그에 맞는 소스 코드를 만들어주는 javac 빌드툴의 일종

  • 어노테이션을 사용하기 위해서는 어노테이션 프로세서가 필요함

  • 모든 어노테이션 프로세서는 AbstractProcessor 추상클래스를 상속 받아야 함

package javax.annotation.processing;

import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Objects;
import javax.lang.model.element.*;
import javax.lang.model.SourceVersion;
import javax.tools.Diagnostic;

public abstract class AbstractProcessor implements Processor {

    protected ProcessingEnvironment processingEnv;
    private boolean initialized = false;

    protected AbstractProcessor() {}

   /*
    * 
    */
    public synchronized void init(ProcessingEnvironment processingEnv) {
        if (initialized)
            throw new IllegalStateException("Cannot call init more than once.");
        Objects.requireNonNull(processingEnv, "Tool provided null ProcessingEnvironment");

        this.processingEnv = processingEnv;
        initialized = true;
    }
   
   /*
    * 각각 프로세의 main() 메소드 역할을 수행
    */
   public abstract boolean process(Set<? extends TypeElement> annotations,RoundEnvironment roundEnv);
    
   public Set<String> getSupportedAnnotationTypes() {
        SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
        if  (sat == null) {
            if (isInitialized())
                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                         "No SupportedAnnotationTypes annotation " +
                                                         "found on " + this.getClass().getName() +
                                                         ", returning an empty set.");
            return Collections.emptySet();
        }
        else
            return arrayToSet(sat.value());
    }

   /*
    * 특정 자바버전을 지정할 때 사용
    *
    * Java 1.6을 사용하고 싶으면 SourceVersion.RELEASE_6 이용
    * 보통 SourceVersion.latestSupported() 사용하는 것을 권장
    */
    public SourceVersion getSupportedSourceVersion() {
        SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class);
        SourceVersion sv = null;
        if (ssv == null) {
            sv = SourceVersion.RELEASE_6;
            if (isInitialized())
                processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                         "No SupportedSourceVersion annotation " +
                                                         "found on " + this.getClass().getName() +
                                                         ", returning " + sv + ".");
        } else
            sv = ssv.value();
        return sv;
    }

    /*
     * 어노테이션 프로세서가 처리할 어노테이션을 명시
     */
    public Set<String> getSupportedAnnotationTypes() {
            SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
            if  (sat == null) {
                if (isInitialized())
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
                                                             "No SupportedAnnotationTypes annotation " +
                                                             "found on " + this.getClass().getName() +
                                                             ", returning an empty set.");
                return Collections.emptySet();
            }
            else
                return arrayToSet(sat.value());
    }

    ....
}
  • 동작 순서

    • 자바 컴파일 실행

    • 어노테이션 프로세서에서 어노테이션에 대한 처리를 함

    • 자바 컴파일러가 모든 어노테이션 프로세서가 실행 되었는지 검사(실행되지 않았다면 반복함)

 

※ 참조

 

 

Annotations Basics (The Java™ Tutorials > Learning the Java Language > Annotations)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

Predefined Annotation Types (The Java™ Tutorials > Learning the Java Language > Annotations)

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

자바 애너테이션 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 자바 애너테이션(Java Annotation)은 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종이다. 보통 @ 기호를 앞에 붙여서 사용한다. JDK 1.5 버전 이상에서

ko.wikipedia.org

 

Annotation Processing 101 (번역)

Hannes Dorfmann 가 작성한 “Annotation Processing 101” 을 원작자의 동의를 받아 번역한 글입니다.

medium.com

 

'Study' 카테고리의 다른 글

[Study-14주차] 제네릭(Generics)  (0) 2021.02.23
[Study-13주차] I/O(입출력)  (0) 2021.02.12
[Study-11주차] Enum  (0) 2021.01.26
[Study-9주차] 예외 처리  (0) 2021.01.12
[Study-8주차] 인터페이스  (0) 2021.01.04