-
어노테이션은 메타데이터기 때문에 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지를 알려주는 정보이다.
어노테이션은 다음 세 가지 용도로 쓰인다.
1. 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공
2. 소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공
3. 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공
어노테이션 타입 정의와 적용
public @interface AnnotationName { }
이렇게 정의한 어노테이션은 코드에서 다음과 같이 사용한다.
@AnnotationName
어노테이션은 엘리먼트를 멤버로 가질 수 있다. 각 엘리먼트는 타입과 이름으로 구성되며, 디폴트 값을 가질 수 있다.
pubic @interface AnnotationName { 타입 elementName() {default 값}; }
어노테이션 적용 대상
어노테이션이 적용될 대상을 지정할 때에는 @Target 어노테이션을 사용한다.
@Target의 기본 엘리먼트인 value는 ElementType 배열을 값으로 가진다.
@Target({ElementType.TYPE,ElementType.FILELD,ElementType.METHOD}) public @interface AnnotationName { }
위와 같은 어노테이션을 정의할 경우에는 클래스,필드,메소드에만 어노테이션이 적용될 수 있다.
@AnnotationName public class ClassName { @AnnotationName private String fieldName; //@AnnotationName (x) ---- @Target에 Construct가 없어 생성자는 적용 못한다. public ClassName() {} @AnnotationName public void methodName() {} }
어노테이션 유지 정책
어노테이션 정의 시 한 가지 더 추가해야 할 내용은 사용 용도에 따라 @AnnotationName을 어느범위까지 유지할 것인지 지정해야 한다. 즉 소스상에서만 유지할 건지, 컴파일도니 클래스까지 유지할 건지, 런타임 시에도 유지할 건지를 지정해야 한다.
SOURCE - 소스상에서만 어노테이션 정보를 유지한다. 소스 코드를 분석할 때만 의미가 있으며, 바이트 코드 파일에는 정보가 남지 않는다.
CLASS - 바이트 코드파일까지 어노테이션 정보를 유지한다. 하지만 리플렉션을 이용해서 어노테이션 정보를 얻을 수는 없다.
RUNTIME - 바이트 코드 파일까지 어노테이션 정보를 유지하면서 리플렉션을 이요해서 런타입 시에 어노테이션 정보를 얻을 수 있다.
(리플렉션이란 런타임 시에 클래스의 메타 정보를 얻는 기능을 말한다. 예를 들어 클래스가 가지고 있은 필드가 무엇인지, 어떤 생성자를 갖고 있는지, 어떤 메소드를 가지고 있는지, 적용된 어노테이션이 무엇인지 알아내는 것이 리플렉션이다.)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface AnnotationName { }
런타임 시 어노테이션 정보 사용하기
getFields() - 필드 정보를 배열로 리턴
getConstructors() - 생성자 정보를 배열로 리턴
getDeclaredMethods() - 메소드 정보를 배열로 리턴
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface PrintAnnotation { String value() default "-"; int number() default 15; }
public class Service { @PrintAnnotation public void method() { System.out.println("실행 내용1"); } @PrintAnnotation("*") public void method2() { System.out.println("실행 내용2"); } @PrintAnnotation(value="#", number=20) public void method3() { System.out.println("실행 내용3"); } }
public class PrintAnnotaionExample { public static void main(String[] args) { //Service 클래스로부터 메소드 정보를 얻음 Method[] declartMethods = Service.class.getDeclaredMethods(); //Method 객체를 하나씩 처리 for(Method method : declartMethods) { //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.println(printAnnotation.value()); } System.out.println(); try { //메소드 호출 method.invoke(new Service()); } catch (Exception e) { System.out.println(); } } } } }
출처 - 이것이 자바다
'자바' 카테고리의 다른 글
자바의 변수(variable)에 대해서 (0) 2021.03.10 JVM(Java Virtual Machine) (0) 2021.03.10 컬렉션 프레임워크 (0) 2019.04.15 제너릭 (0) 2019.04.14 예외처리 (0) 2019.04.09