Annotation과 Reflection

현시기얌·2022년 2월 21일

Reflection

목록 보기
2/4

중요 Annotation

  • @Retention : 해당 애노테이션을 언제까지 유지할 것인가? 소스, 클래스, 런타임
  • @Inherit : 해당 Annotation을 하위 클래스까지 전달할 것인가?
  • @Target : 어디에 사용할 수 있는가?

예제 코드

public @interface MyAnnotation {
}

@MyAnnotation
public class Book {

    private static String B = "Book";
    private static final String C = "Book";

    private String a = "a";

    public String d = "d";

    protected String e = "e";

    public Book() {

    }

    public Book(String a, String d, String e) {
        this.a = a;
        this.d = d;
        this.e = e;
    }

    private void f() {
        System.out.println("F");
    }

    public void g() {
        System.out.println("G");
    }

    public int h() {
        return 1000;
    }
}

public class App {

    public static void main(String[] args) {
        Arrays.stream(Book.class.getAnnotations()).forEach(System.out::println);
    }
}

위와 같이 Book Class의 Annotation을 조회할려고 하면 조회가 되지 않는다. 왜냐하면 Annotation은 주석과 비슷하게 작동되어서 정보가 소스,Class까지는 남지만 바이트코드를 로딩하는 시점에는 남지 않는다. 즉 런타임 시에는 작동되지 않는다.

@Retention

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}

때문에 위와 같이 런타임시 까지 유지되도록 할려면 위와 같은 @Retention 애노테이션을 붙여주면 된다.

실행결과

@Target

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {
}

@Target 애노테이션을 사용해서 Annotation의 위치를 지정할 수 있다.

Annotation에 값 가지기

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation {

    String value();

    String name() default "hyun6ik";

    int number() default 100;

}

default를 사용해서 기본 값 또한 지정할 수 있다.
또한 value를 지정하면

@MyAnnotation("hello")
public class Book {

위와 같이 명시할 필요없이 바로 사용 가능하다. (parameter가 2개 이상일 시 value= 같이 지정해야한다.)

@Inherited

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@Inherited
public @interface MyAnnotation {

    String value();

    String name() default "hyun6ik";

    int number() default 100;

}

위와 같이 @Inherited 애노테이션을 지정하면 MyAnnotation을 적용한 클래스의 하위 클래스까지도 애노테이션이 적용된다.

public class MyBook extends Book implements MyInterface{
}

public class App {

    public static void main(String[] args) {
        Arrays.stream(MyBook.class.getAnnotations()).forEach(System.out::println);
    }
}

실행 결과

Reflection

  • getAnnotation() : 상속 받은(@Inherit) 애노테이션까지 조회
  • getDeclaredAnnotations : 자기 자신에만 붙어있는 애노테이션 조회

Field의 Annotation

Field의 Annotation은 Annotation의 정보를 꺼내서 참조할 수 있다.

        Arrays.stream(Book.class.getDeclaredFields()).forEach(f -> {
            Arrays.stream(f.getAnnotations()).forEach(a -> {
                if (a instanceof AnotherAnnotation) {
                    final AnotherAnnotation anotherAnnotation = (AnotherAnnotation) a;
                    System.out.println(anotherAnnotation.number());
                    System.out.println(anotherAnnotation.name());
                }
            });
        });
profile
현시깁니다

0개의 댓글