Java Annotation

애너테이션이란?

  • 자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기보다 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다.
  • 소스코드의 주석에 소스코드에 대한 정보를 저장하고, 소스코드의 주석으로부터 HTML 문서를 생성해내는 프로그램(javadoc.exe)를 만들어 사용했다.
  • 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 애너테이션
  • 애너테이션은 주석과 같이 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다.
  • @Test 애너테이션은 테스트 프로그램인 JUnit에게 테스트를 해야한다고 알리기만 할 뿐 메서드가 포함된 프로그램 자체에는 아무런 영향을 미치지 않는다. 즉, 다른 프로그램에게 어떤 역할 하는지 알려주는 주석이다.
  • java.lang.annotation 에 포함된 JDK 에서 제공하는 표준 애너테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공한다.
  • 애너테이션은 다이나믹하게 실행되는 코드는 들어가지 않는다. 즉, 런타임 중에 알아내야 하는 값은 들어가지 못한다. 컴파일러 수준에서 해석이 되거나, 완전히 정적이어야 하며 동적으로 런타임 중에 바뀌어야 하는 것들은 애너테이션으로 사용할 수 없다.
  @RestController
  public DemoController {
    private static final String path = "ex";

    @GetMapping(path)
    public String ex() {
      return "ex";
    }
  }

  • path 변수는 static final 정적 변수로 @GetMapping 애너테이션에 사용할 수 있다. 만약 path 변수가 동적으로 할당된다면 컴파일 에러 발생

애너테이션 정의

  public @interface TestAnnotation {
  }
  • 애너테이션은 element라는 것을 멤버로 가질 수 있다.
  @TestAnnotation(name = "chae", age = 19)
  public class Test {
  }
  
  @interface TestAnnotation {
    String name();
    int age();
  }
  • 애너테이션에 기본값 설정
  @TestAnnotation
  public class Test {
  }
  
  @interface TestAnnotation {
    String name() default "chae";
    int age() default 19;
  }
  • 애너테이션은 value라는 기본 element를 가질 수 있다.
  • value라는 element는 애너테이션을 적용할 때 굳이 element의 이름을 명시해주지 않아도 된다.
  • 두 개 이상의 element 값을 할당해야하는 경우 value 명시
  @TestAnnotation("chae")
  public class Test {
  }
  
  @interface TestAnnotation {
    String value();
  }

자바 표준 애너테이션

  • 자바에서 기본적으로 제공하는 애너테이션으로 built-in annotation 이라고도 한다.
애너테이션 설명
@Override 오버라이딩 된 메서드에 사용
@Deprecated 사용을 권장하지 않는 메서드에 사용
@SuppressWarnings 컴파일 경고를 무시하도록 할 때 사용
@SafeVarargs 가변인자 parameter 사용시 경고를 무시할 때 사용(JDK 1.7이상)
@FunctionalInterface 함수형 인터페이스임을 명시할 때 사용(JDK 1.8이상)

자바 메타 애너테이션

  • 애너테이션을 위한 애너테이션
  • 애너테이션을 정의할 때 애너테이션의 적용대상, 유지기간 등을 지정하는데 사용한다.

@Target

  • 애너테이션 적용가능 대상을 지정하는데 사용
  • 애너테이션과 관련하여 java.lang.annotation.ElementType 이라는 enum 타입이 정의되어 있다.
ElementType 적용대상
TYPE class, interface, enum
ANNOTATION_TYPE annotation
FIELD field
CONSTRUCTOR constructor
METHOD method
LOCAL_VARIABLE local variable
PACKAGE package
@Target({ElementType.FIELD, ElementType.METHOD})
@interface TestAnnotation {
}

@Retention

  • 애너테이션 정보를 언제까지 유지할 것인지 정하는데 사용
  • 이 유지 정책은 java.lang.annotation.RetentionPolicy 라는 enum 타입으로 정의되어 있다.
유지정책 설명
SOURCE 소스 파일에만 존재. 클래스 파일(바이트코드)에는 존재하지 않음
CLASS(기본값) 클래스 파일에 존재. 실행 시에는 사용불가(리플렉션으로 정보를 얻을 수 없음)
RUNTIME 클래스 파일에 존재. 실행 시에 사용가능(리플렉션으로 정보를 얻을 수 있음)
public class Test {
  public static void main(String[] args) throws ClassNotFoundException {
    Class clazz = Class.forName("com.spring.ReflectionTestClass");
    Annotation[] annotations = clazz.getDeclaredAnnotations();
    for (Annotation annotation : annotations) {
      System.out.println("annotation : " + annotation.toString());
    }
  }
}

@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation { }

@TestAnnotation
class ReflectionTestClass { }

  • @Retention 으로 기본으로 설정된 CLASS 유지정책을 RUNTIME으로 변경하면 리플렉션으로 클래스의 정보를 얻을 수 있다.

@Documented

  • 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.
  • 자바에서 제공하는 기본 애너테이션 중 @Override, @SuppressWarnings를 제외한 모든 표준 애너테이션에 붙어있다.

Categories:

Updated:

Comments