2021-06-21 강의록_어노테이션

11198 단어 JavaJava

어노테이션

  • 프로그램에 추가적인 정보를 제공해주는 메타데이터(metadata)
  • 컴파일러에게 코드 작성 문법 에러 체크하도록 정보 제공
  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동 생성하게 정보 제공 (대표적으로 lombok)
  • 실행 시(런타임 시) 특정 기능 실행하도록 정보 제공

    예: @Override
    안붙여도 되지만, 붙이면 컴파일러가 해당 문법을 더 강력하게 체크함.
    내가 만든 프로그램 내에서 다르게 동작하게 한다.

  • 어노테이션도 참조타입이다. 따라서 import가 필요한 것.
  • 어노테이션을 사용한다는 것은, 이 메타데이터를 이용할 누군가가 있다는 뜻.

기본 엘리먼트(속성) value

public @interface AnnotationName {
 //Element (속성)
 String value();
 int elementName() default 5;
}
  • 타입은 무관하고, 속성 이름이 value() 인 속성을 default element, 기본 속성이라고 함.

  • () <<붙어있어서 필드는 아니고, 실행블록이 없으니 메소드도 아니다.

  • 어노테이션 사용시 외부에서 값을 받아올 수 있는데, 이 때 전달받을 값이 없으면 default 의 값을 갖게된다. (default 구문이 있으면 어노테이션 사용시 전달값을 생략해도 되지만, default 구문이 없으면 반드시 전달값이 있어야 한다.
    -> 어노테이션의 목적이 메타데이터 제공이니까!!

  • 어노테이션 속성의 타입으로는
    1) 기본타입(Primitive type)
    2) String
    3) 열거타입(Enumeration type)
    4) Class타입(Clazz) >> 참조타입의 Class타입 아님!!! java.lang.Class 임!!!
    5) 위의 1~4까지의 타입으로 구성된 배열(Array)
    을 쓸 수 있다.

    참조타입의 클래스, 인터페이스는 사용할 수 없다.
    annotation 은 메타데이터를 제공하지만, 아주 많은 양의 데이터를 제공하는 것은 아님.
    따라서 기본타입이나 String, 배열 정도로도 충분히 표현이 가능함.

어노테이션의 속성이 곧, 메타데이터를 보관할 장소이다.

어노테이션 적용할 때, 기본속성(value)에만 값을 전달할 경우엔 속성 이름 생략 가능
@AnnotationName("값");

두 개 이상의 속성을 기술할 때에는 value = 값 형태로 기술
@AnnotationName(value = "값", elementName=3;)


@Retention(RetentionPolicy. ~~~)

선언된 어노테이션이 언제까지 유효한지 지정.

@Retention(RetentionPolicy.[RUNTIME | SOURCE | CLASS)

class, runtime 둘 다 바이트코드에
실행시점에 보이지 않는다.
runtime시에도 보이게하려면 runtime으로 지정해야 한다. (대부분 RUNTIME임)

@Target({ElemetType.~~~})

기본타입 속성이 열거타입으로 된 배열.
어노테이션을 클래스의 어느 부분에 적용할 수 있는지를 ElementType 열거상수들로 지정

@Target({ElementType.TYPE,
	ElementType.FIELD,
	ElementType.PARAMETER,
	ElementType.METHOD,
	ElementType.CONSTRUCTOR,
	ElementType.LOCAL_VARIABLE,	//지역변수
	ElementType.ANNOTATION_TYPE,	//어노테이션 선언부
	ElementType.PACKAGE,})


package annotation;

import java.lang.reflect.Method;

import lombok.extern.log4j.Log4j;



@Log4j
public class PrintAnnotationEx {
	
	//Service클래스에 붙인 어노테이션 정보를 이용해서, 어노테이션이 장착된 메소드에 대해 특수한 기능 수행하기
	public static void main(String[] args) {
		
		// 1. Service 클래스의 Clazz객체 얻어냄
		Class<Service> clazz = Service.class;

		// 2. Clazz객체로부터, Service 클래스에 선언된 모든 메소드 정보를 배열로 획득
		Method[] declaredMethods = Service.class.getDeclaredMethods();

		// 3. Method 객체를 하나씩 처리
		for (Method method : declaredMethods) {
			
			// 4. PrintAnnotation이 어느 메소드에 적용되었는지 확인
			if (method.isAnnotationPresent(PrintAnnotation.class)) {
				
				// 4-1. PrintAnnotation 객체 얻기
				PrintAnnotation printAnnotation = 
						//Method 타입의 메소드 중에, 어노테이션을 반환하는 메소드가 있음
						// 즉, Method.getAnnotation(Clazz)
						method.getAnnotation(PrintAnnotation.class);

				// 4-2. 메소드 이름 출력 (>> 호출로그를 따로 작성하지 않아도 메소드명을 얻을 수 있음)
				log.info("[" + method.getName() + "] ");
				
				// 4-3. 구분선 출력
				// PrintAnnotation의 속성중에, number()속성값을 이용
				// (필드처럼 보이지만, 실제 사용할 때에는 메소드 처럼 사용)
				for(int i=0; i<printAnnotation.number(); i++) {
					System.out.print(printAnnotation.value());
				} //classical for
				
				log.info(declaredMethods);;
				
             		        // 4-4. Method타입이 객체를 가지고, Service 클랫에 선언된 메소드를 실제 호출
				try {
					//메소드 호출
					method.invoke (new Service());
				} catch (Exception e ) {;;} //try-catch
				
				log.info("");
			} // if
		} //enhanced for
		 
	} //main
	
} //end class

POJO

Plain Old Java Object
extends도 받지 않고, implements도 하지 않은 평범한 객체(클래스)

좋은 웹페이지 즐겨찾기