스터디/LiveStudy

12주차 과제 : 애노테이션

TheWing 2021. 1. 31. 19:42

12주차 과제: 애노테이션

목표

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

학습할 것 (필수)

  • 애노테이션 정의하는 방법
  • @retention
  • @target
  • @documented
  • 애노테이션 프로세서

어노테이션

  • 클래스나 메소드 등의 선언시에 @를 사용하는 것을 말한다. 메타데이터(Metadata)라고도 불린다

어노테이션의 사용

  • 컴파일러에게 정보를 알려주거나

  • 컴파일할 때와 설치시의 작업을 지정하거나

  • 실행할 때 별도의 처리가 필요할 때

  • 어노테이션은 클래스, 메소드, 변수 등 모든 요소에 선언할 수 있다

어노테이션 정의하는 방법

어노테이션 선언 예제)

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 UserAnnotation {
    public int number();
    public String text() default "This is first annotation";
}
  • @Target 은 해당 어노테이션 사용 대상을 지정한다. 여기서는 ElementType.METHOD를 소괄호 안에 넣어 줌으로써 이 어노테이션은 메소드에 사용할 수 있다고 지정된것이다.
  • @Retention 은 어노테이션 유지 정보를 지정하는 데 사용한다. 소괄호 안에 RetentionPolicy.RUNTIME으로 지정하면 실행시에 이 어노테이션을 참조하게 된다.
  • 어노테이션 이름인 UserAnnotation@interface로 선언하면 @UserAnnotation 으로 어노테이션이 사용가능해진다
  • 어노테이션 선언 안에는 number() 라는 메소드와 text()라는 메소드가 있다. number()의 리턴 타입은 int 이며, text() 리턴타입은 String이다 이렇게 메소드 처럼 어노테이션 안에 선언해 놓으면, 이 어노테이션을 사용할 때 해당 항목에 대한 타입으로 값을 지정가능하다.
  • text()를 보면 default라는 예약어를 쓴 뒤 문자열이 지정되어 있는 것을 볼 수 있다. default예약어를 사용할 경우에는 default 뒤에 있는 값이 이 어노테이션을 사용할 때의 기본값이 된다. 즉 값을 지정하지 않아도 default값으로 지정된다.

예시

  • 몰라도된다
public class UserAnnotationSample {
    @UserAnnotation(number = 0)
    public static void main(String[] args) {
        UserAnnotationSample sample = new UserAnnotationSample();
    }

    @UserAnnotation(number = 1)
    public void annotationSample1() {

    }

    @UserAnnotation(number = 2, text = "second")
    public void annotationSample2() {

    }

    @UserAnnotation(number = 3, text = "third")
    public void annotationSample3() {

    }

}
public class UserAnnotationCheck {
    public static void main(String[] args) {
        UserAnnotationCheck sample = new UserAnnotationCheck();
        sample.checkAnnotations(UserAnnotationSample.class);
    }

    public void checkAnnotations(Class useClass) {
        Method[] methods = useClass.getDeclaredMethods();
        for(Method tempMethod : methods){
            UserAnnotation annotation = tempMethod.getAnnotation(UserAnnotation.class);
            if (annotation != null){
                int number = annotation.number();
                String text = annotation.text();
                System.out.println(tempMethod.getName() + "() : number=" + number + " text=" + text);
            } else {
                System.out.println(tempMethod.getName()+"() : annotation is null");
            }
        }
    }
}
  • Class 클래스에 선언되어 있는 getDeclaredMethods() 메소드를 호출하면, 해당 클래스에 선언되어 있는 메소드들의 목록을 배열로 리턴한다
  • Method 클래스에 선언되어 있는 getAnnotation() 이라는 메소드를 호출하면, 해당 메소드에 선언되어 있는 매개 변수로 넘겨준 어노테이션이 있는지 확인하고 있을 경우 그 어노테이션의 객체를 리턴해준다
  • 어노테이션에 선언된 메소드를 호출하면 그 값을 리턴해준다
main() : number=0 text=This is first annotation
annotationSample1() : number=1 text=This is first annotation
annotationSample2() : number=2 text=second
annotationSample3() : number=3 text=third

JDK 6까지 미리 정해져 있는 어노테이션

  • @Override
  • @Deprecated
  • @SupressWarnings

@Override

  • 해당 메소드가 부모 클래스에 있는 메소드를 Override했다는 것을 명시적으로 선언한다
  • 명확하게 이 메소드는 Override 된거이므로 컴파일러에게 맞는지 물어본다.

@Deprecated

  • 미리 만들어져 있는 클래스나 메소드가 더 이상 사용되지 않는 경우 컴파일러에게 "더이상 사용하지 않으니 사용하게되면 경고를 달라" 명시한다.

@SupressWarings

  • 컴파일할 때 경고를 안줘도 된다고 말해주는것

@Override 예제

public class AnnotationOverride extends Parent {
    @Override
    public void printName() {
        System.out.println("AnnotationOverride");
    }
}
public class Parent {
    public Parent() {
        System.out.println("Parent Constructor");
    }

    public void printName() {
        System.out.println("Parent printName()");
    }
}

이걸

public class AnnotationOverride extends Parent {
    @Override
    public void printName(String args) {
        System.out.println("AnnotationOverride");
    }
}

이렇게 변경하면 에러가 발생한다

@Deprecated

  • 컴파일 경고가 발생한다

사용하는 이유

  • 협업에서 개발을 할 때 다른 개발자가 개발한것을 지우면 안되기 때문

어노테이션을 선언하기 위한 메타 어노테이션

  • 메타 어노테이션 (Meta Annotation) 은 어노테이션을 선언할 때 사용한다

메타 어노테이션 종류

  • @Target
  • @Retention
  • @Documented
  • @Inherited

@Target

  • 어노테이션을 어떤 것에 적용할지를 선언할 때 사용한다.

      @Target(ElementType.METHOD)

 

@Retention

  • 얼마나 오래 어노테이션 정보가 유지되는지
@Retention(RetentionPolicy.RUNTIME)

@Target 처럼 괄호 안에 지정하는 적용 가능한 대상은 다음과 같다

 

@Documented

  • 해당 "어노테이션에 대한 정보가 Javadocs(API)문서에 포함된다는 것"을 선언

@Inherited

  • 모든 자식 클래스에서 부모 클래스의 어노테이션을 사용가능하다는 것을 선언한다.

어노테이션에는 상속이 안된다

  • enum 클래스가 상속을 지원하지 않듯이 어노테이션을 선언할 때도 미리 만들어 놓은 어노테이션을 확장하는것이 불가능하다. 재사용이 불가능하다.
  • 어노테이션을 만드는이유?
    • 제약사항 등을 선언하기 위해
      • @Deprecated, @Override, @NotNull
    • 용도를 나타내기 위해
      • @Entity, @TestCase, @WebService
    • 행위를 나타내기 위해
      • @Statefull, @Transaction
    • 처리를 나타내기 위해
      • @Column, @XmlElement

어노테이션 프로세서

어노테이션 프로세서란?

  • 자바 컴파일러의 컴파일 단계에서, 유저가 정의한 어노테이션의 소스코드를 분석하고 처리하기 위해 사용되는 훅이다. 컴파일 에러나 컴파일 경고를 만들어 내거나, 소스코드(.java)와 바이트코드(.class)를 내보내기도 한다

어노테이션 프로세서 사용 예제

  • Lombok
  • AutoService : java.util.ServiceLoader 용 파일 생성 유틸리티
  • @Override
  • Dangger 2 : 컴파일 타임 DI 제공

어노테이션 프로세서 장점

  • 런타임 비용이 없음(컴파일 타임에 조작이 완료된 상황이기 때문에)

어노테이션 프로세싱의 애플리케이션

  • 소스 레벨 어노테이션 프로세싱은 Java5부터 나타났다. 이는 컴파일 단계에서 추가 소스 파일을 생성하는 편리한 기술이다
  • 소스 파일이 Java 파일 일 필요는 없다. 소스 코드의 어노테이션을 기반으로 모든 종류의 설명, 메타 데이터, 문서, 리소스 또는 기타 모든 유형의 파일을 생성할 수 있다.
  • 중요한 점은 어노테이션 프로세서 API의 한계이다. 기존 파일을 변경하지 않고 새 파일을 생성하는 데만 사용할 수 있다.

어노테이션 프로세싱 API

  • 어노테이션 프로세싱은 여러 라운드로 수행된다. 각 라운드는 컴파일러가 소스 파일에서 어노테이션을 검색하고 이러한 어노테이션에 적합한 어노테이션 프로세서를 선택하는 것으로 시작된다. 차례로 각 어노테이션 프로세서는 해당 소스에서 호출된다.
  • 프로세스 중에 파일이 생성되면 생성된 파일을 입력으로 사용하여 다른 라운드가 시작이된다. 이 프로세스는 처리단계에서 새 파일이 생성되지 않을 때까지 계속된다
  • 각 어노테이션 프로세서는 해당 소스에서 차례로 호출된다. 이 프로세스 중에 파일이 생성되면 생성된 파일을 입력으로 사용하여 다른 라운드가 시작된다. 이 프로세스는 처리 단계에서 새 파일이 생성되지 않을 때까지 계속된다.
  • 어노테이션 처리 API는 javax.annotation.processing 패키지에 있다. 구현해야 할 주요 인터페이스는 AbstractProcessor 클래스 형태의 부분 구현이 있는 프로세서 인터페이스다 이 클래스는 자체 주석 프로세서를 만들기 위해 확장할 클래스이다

Reference

'스터디 > LiveStudy' 카테고리의 다른 글

14주차 과제: 제네릭  (0) 2021.02.21
13주차 과제 : I/O  (0) 2021.02.08
11주차 과제: Enum  (0) 2021.01.25
10주차 과제: 멀티쓰레드 프로그래밍  (6) 2021.01.18
9주차 과제: 예외 처리  (0) 2021.01.11