Archive/Java

자바 @어노테이션 정리 2편

nimkoes 2017. 6. 3. 10:23
728x90

 

런타임시에 어노테이션 정보 사용하기

 

 

 

클래스에 적용된 어노테이션 정보 얻기

 

- 클래스.class 의 어노테이션 정보를 얻는 메소드를 이용한다.

 

필드, 생성자, 메소드에 적용된 어노테이션 정보 얻기

 

- 클래스.class의 다음 아래 표에 작성된 메소드를 이용해서

- java.lang.reflect 패키지의 Field, Constructor, Method 클래스의 배열을 얻어낸다.

 

리턴타입 메서드명 (매개변수) 설명
Field[] getFields() 필드 정보를 Field 배열로 반환
Constructor[] getConstructor() 생성자 정보를 Constructor 배열로 반환
Method[] getDeclaredMethods() 메소드 정보를 Method 배열로 반환

 

- Field, Constructor, Method의 어노테이션 정보를 얻는 메소드를 이용

 

예를 들어 다음과 같은 코드가 있다.

 

class TestAnno {
    @Annotation1
    int field1;
    
    @Annotation2
    String field2;
}

 

TestAnno 클래스에는 field1, field2 필드가 선언되어 있고 각 필드는 Annotation이 적용되어 있다.

이럴 경우 위 표에 작성한 Field[]를 사용하여 각 필드를 배열로 저장하고, 이 배열에 저장된 내용을 가지고 각 필드에 어떤 어노테이션이 적용되었는지 알아올 수 있다. (생성자와 메서드도 동일하다.)

 

 

 

 

어노테이션 정보를 얻기 위한 메소드

 

리턴타입 메소드명 (매개변수)
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
지정한 어노테이션이 적용되었는지 여부, Class에서 호출했을 경우 상위 클래스에 적용된 경우에도 true를 리턴한다.
Annotation getAnnotation(Class<T> annotationClass)
지정한 어노테이션이 적용되어 있으면 어노테이션을 리턴하고 그렇지 않다면 null을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 경우에도 어노테이션을 리턴한다.
Annotation[] getAnnotations()
적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스(부모클래스)에 적용된 어노테이션도 모두 포함한다. 적용된 어노테이션이 없을 경우 길이가 0인 배열을 리턴한다.
Annotation[] getDeclaredAnnotations()
직접 적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 어노테이션은 포함되지 않는다.

 

아래 예제를 통해 어떻게 사용하는지 직접적으로 알아보자.

순서는 다음과 같다.

1. 어노테이션 생성

2. 어노테이션이 적용된 소스 작성

3. 어노테이션이 적용된 소스를 실행할 메인 클래스 작성

 

 

1. 어노테이션 생성

 

/*
 * 이 어노테이션은 Method에만 적용될 수 있음을 명시한다.
 * 또한 실행시에도 유지되어야 하므로 Runtime 유지 정책을 명시한다.
 */
@Target()
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintAnnotation {
    /*
     * 이름 : value
     * 리턴타입 : String
     * 기본값 : "-"
     */
    String value() default "=";

    /*
     * 이름 : number
     * 리턴타입 : int
     * 기본값 : 15
     */
    int number() default 15;
}

[PrintAnnotation.java 파일]

 

 

 

2. 어노테이션이 적용된 소스 작성

 

public class Service {
    @PrintAnnotation
    public void method1() {
        System.out.println("실행 내용1");
    }

    @PrintAnnotation("*")
    public void method2() {
        System.out.println("실행 내용2");
    }

    @PrintAnnotation(value="#", number=20)
    public void method3() {
        System.out.println("실행 내용3");
    }
}

[Service.java 파일]

 

 

 

3. 어노테이션이 적용된 소스를 실행할 메인 클래스 작성

 

import java.lang.reflect.*;

public class PrintAnnotationExample {
    public static void main(String[] ar) {
        // Service 클래스에 어노테이션이 적용된 메서드가 있는지 조사한다.
        // 어노테이션의 element 값을 사용한다.
        // 해당 메서드를 호출한다.

        Method[] declaredMethods = Service.class.getDeclaredMethod();

        for(Method method : declaredMethods) {
            // 현재 method에 PeintAnnotation 어노테이션이 적용되어있는지 검사
            if(method.isAnnotationPresent(PrintAnnotation.class)) {
                // 적용되어 있을 경우 진입

                PrintAnnotation printAnnotation = method.getAnnotation(PrintAnnotation.class);

                // 메소드 이름 출력
                System.out.println("[" + method.getName() + "]");

                // 어노테이션에 만든 element에 대해 값을 가져올 때 아래와 같이 가져올 수 있다.
                // System.out.println(printAnnotation.value());
                // System.out.println(printAnnotation.number());

                for(int i = 0; i < printAnnotation.number(); ++i) {
                    System.out.print(printAnnotation.value());
                }
                System.out.println();

                // 현재 반복문에 들어와 있는 메서드 호출
                try {
                    // 메서드가 들어있는 클래스 객체를 매개변수로 넘겨준다.
                    // 아래 한 줄은 마치
                    // Service service = new Service();
                    // service.method1();
                    // 과 같은 역할을 한다고 생각하면 된다.
                    method.invoke(new Service());
                } catch (Exception e) {
                }
                System.out.pritnln();
            }
        }
    }
}

[PrintAnnotationExample.java 파일]

 

실행 결과

[method1]
---------------
실행 내용1

[method2]
***************
실행 내용2

[method3]
####################
실행 내용3

 

사실 어노테이션을 직접 정의해서 사용하는 일은 그렇게 흔한 일은 아니다. (라고 알고 있다.)

하지만 직접 작성해보고 사용해보는 과정을 통해서 나중에 api에서 제공해주는 어노테이션을 만났을 때 소스 분석에 더 도움이 될거라고 생각하고 도서를 참고하여 어노테이션에 대해 정리해보았다.

 

나는 도움이 되었는데 누군가도 도움이 되었으면 좋겠다.

 

 

 

내용 참고 ] 이것이 자바다(신용권의 Java 프로그래밍 정복). 한빛미디어 출반사. 신용권 저.

 

 

 

 

728x90