어노테이션의 경우 원래 아무런 동작을 하지 않는 단순한 표식 혹은 정보 값에 지나지 않을 수 있지만, 앞서 살펴본 리플렉션(Reflextion)을 통해서 정보를 획득하고, 일정한 처리를 진행할 수 있도록 지원하고 있습니다. 일단 클래스 / 필드 / 생성자 / 메서드에 적용된 어노테이션 정보를 획득해야 합니다.
클래스에 적용된 어노테이션 정보 획득을 위해서는 java.lang.Class를 이용하면 되는데 필드 / 생성자 / 메서드에 적용된 어노테이션 정보 획득을 위해서는 Class의 메서드를 통해서 java.lang.reflect 패키지의 Field, Constructor, Method 타입의 배열을 얻어야 합니다.
Return Type | Method Name(Parameter) | Description |
Field[] | getFields() | 필드 정보를 Field 배열로 리턴한다. |
Constructor[] | getConstructors() | 생성자 정보를 Constructor 배열로 리턴한다. |
Method[] | getDeclaredMethods() | 메서드 정보를 Method 배열로 리턴한다. |
이제 위의 절차를 거쳐 획득한 Class, Field, Constructor, Method가 가진 아래의 메서드를 호출하게 되면 각각의 객체에 적용된 어노테이션 정보를 확인할 수 있게 됩니다.
Return Type | Method Name(Parameter) |
boolean | isAnnotationPresent(Class<? extends Annotation> annotationClass) |
지정한 어노테이션이 적용되었는지 여부를 리턴한다. Class에서 호출했을 때, 상위클래스에 적용된 경우에도 true를 리턴한다. | |
Annotation | getAnnotation(Class<T> annotationClass) |
지정한 어노테이션이 적용되어 있으면 해당 어노테이션을 리턴하고, 아닐 경우 null을 리턴한다. Class에서 호출했을 때, 상위클래스에 적용된 경우에도 적용된 어노테이션을 리턴한다. | |
Annotation[] | getAnnotations() |
적용된 모든 어노테이션을 리턴하며, 없을 경우 길이 0의 배열을 리턴한다. Class에서 호출했을 때, 상위클래스에 적용된 경우에도 적용된 어노테이션도 모두 포함해 리턴한다. | |
Annotation[] | getDeclaredAnnotations() |
직접 적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 때, 상위 클래스에 적용된 어노테이션은 포함되지 않는다. |
예제를 확인해 보겠습니다. 아래 PrintAnnotation을 통해 각 메서드의 실행 내용을 "-" 구분선으로 분리해 출력하게 만들어 보겠습니다.
/* PrintAnnotation.java*/
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintAnnotation {
String value() default "-";
int number() default 15;
}
/* Service.java */
public class Service {
@PrintAnnotation
public void method1() {
System.out.println("result 1");
}
// value 값 변경
@PrintAnnotation("*")
public void method2() {
System.out.println("result 2");
}
// value, number 값 변경
@PrintAnnotation(value = "#", number = 20)
public void method3() {
System.out.println("result 3");
}
}
/* ExampleMain.java */
import java.lang.reflect.*;
public class ExampleMain {
public static void main(String[] args) {
// 리플렉션으로 Service 클래스의 메서드 획득
Method[] declaredMethods = Service.class.getDeclaredMethods();
// *Method 배열 객체를 하나씩 처리한다*
for(Method method : declaredMethods) {
// PrintAnnotation이 적용되었는지를 확인하고
if(method.isAnnotationPresent(PrintAnnotation.class)) {
// 적용되어 있다면, PrintAnnotation 객체를 얻은 다음
PrintAnnotation printAnnotation = method.getAnnotation(PrintAnnotation.class);
// 메서드 이름을 먼저 출력하고
System.out.println("[" + method.getName() + "] ");
// 구분선을 길게 출력한다
for(int i = 0; i < printAnnotation.number(); i++) {
System.out.print(printAnnotation.value());
}
System.out.println();
// 마지막으로 해당 메서드를 실행해 준다.
// invoke()는 Service 객체를 생성하고, 생성된 Service 객체 메서드를 호출한다.
try {
method.invoke(new Service());
} catch (Exception e) {}
System.out.println();
}
}
}
}
'Programming > JAVA' 카테고리의 다른 글
상속(3) - 메서드 재정의(override) 2 (0) | 2023.02.22 |
---|---|
상속(3) - 메서드 재정의(override) 1 (0) | 2023.02.20 |
상속(2) - 부모 생성자의 호출(super) (0) | 2023.02.18 |
상속(1) - 상속의 기본 개념 (0) | 2023.02.17 |
어노테이션(Annotation) - 어노테이션 유지(Retention) 정책 (0) | 2023.02.14 |