ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 어노테이션
    자바 2019. 9. 17. 18:26

    어노테이션은 메타데이터기 때문에 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지를 알려주는 정보이다.

     

    어노테이션은 다음 세 가지 용도로 쓰인다.

    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
Designed by Tistory.