본문 바로가기
study/JAVA

어노테이션(Annotation)

by Elfen Lied 2022. 2. 22.
반응형

- 어노테이션 용도

  • 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공 (메서드 재정의 여부 확인 - @Override)
  • 개발 툴에서 빌드나 배치 시 코드 자동 생성할 수 있게 정보 제공 (XML 설정 파일 자동 생성하거나 배포를 위한 JAR 압축파일 자동 생성 등)
  • 실행 시(런타임 시) 특정 기능 실행하도록 정보 제공 (객체가 애플리케이션 내부에서 할 역할을 정의 가능 (서블릿, 컨트롤러...)

 

- 어노테이션 엘리먼트 멤버

public @interface AnnotationName {
	타입 elementName() [default 값];
    ...
}

엘리먼트 "타입"은 기본 타입과 참조 타입 모두 사용 가능.

 

<!-- 타입 작성 예시 -->

public @interface PrintAnnotation {
	String elementName1();
	int elementName2() default 5;
}

 

 

- 기본 엘리먼트 : value

어노테이션 적용 코드에서 값만 주면 value() 값으로 들어간다.

[1]  @AnnotationName("값") <===== 값만 주면!


public @interface AnnotationName {
	[2]  String value();  <================= 기본 엘리먼트의 값으로 들어감
	int elementName() default 5;
}

 

  1.  원칙은 @AnnotationName(value="값") 으로 쓰나 value= 는 생략 가능
  2. 단! 두 개 이상의 속성을 쓸때는 엘리먼트 명과 값으로 작성해야 함.
  3. 작성 예시 : @AnnotationName(value="값", elementName=3)

 

 

- 어노테이션 적용 대상

ElementType 열거 상수 적용 대상
TYPE 클래스, 인터페이스, 열거 타입
ANNOTATION_TYPE 어노테이션
FIELD 필드
CONSTRUCTOR 생성자
METHOD 메서드
LOCAL_VARIABLE 로컬 변수
PACKAGE 패키지

 

 


- 실습

1. 이클립스에서 ctrl + n 혹은 생성 아이콘을 눌러서 Annotation을 생성해주고 엘리먼트를 선언한다.

public @interface PrintAnnotation {
	String value() default "-";
	int number() default 15;
}

코드는 "-" 하이픈을 15개 출력하겠다는 것 ( --------------- )

 

 

작성했다면 최상단에 다음과 같이 작성한다.

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintAnnotation {
	String value() default "-";
	int number() default 15;
}

@Target 부분을 보면 마지막에 .METHOD가 붙었는데 이는 메서드에만 적용 할수 있다는 뜻.

즉, PrintAnnotation 은 메서드에만 적용할 수있다는 뜻.

 

@Retention 부분은 어노테이션의 유지 정책으로 언제까지 어노테이션 정보가 유지될 거냐라는 것을 뜻한다.

 

 

2. Service 클래스를 생성한다.

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");
	}
}

 

 

3. 실행 클래스를 만든다. (PrintAnnotaionExample 클래스를 만들어준다.)

public class PrintAnnotationExample {
	
	public static void main(String[] args) {
		Method[] declaredMethods = Service.class.getDeclaredMethods();
			
}

Method [] 부분에 빨간 줄이 뜨면 import가 안된 것이기 때문에 ctrl + shift + o를 눌러서 import 해준다.

 

public class PrintAnnotationExample {
	
	public static void main(String[] args) {
		Method[] declaredMethods = Service.class.getDeclaredMethods();
		
		for(Method method : declaredMethods) {
			if(method.isAnnotationPresent(PrintAnnotation.class)) {
				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();
				
				// 메소드 호출				
				method.invoke(new Service());
			
			}
		}
		
	}
}

## for문 안에 있는 System.out.print의 print"ln"이 아니라 print이니 잘 작성하자.

 

 

method.invoke(new Service()) 코드를 해석해보면

>> Service 객체가 가지고 있는 method 이름을 호출한다 << 로 보면 된다.

 

!! method.invoke(new Service()) 코드를 쓰면 빨간 줄이 뜨는데 이유는 예외처리를 해줘야 하기 때문이다.

해당 코드에 커서를 올리고 ctrl + 1 눌러서 surround with try/catch를 만들자

 

 

그리고 아래 코드처럼 수정하자. (예외 처리는 예외처리 공부할 때 하기 때문에 간단하게 수정함)

=================== 이랬던 코드를 ======================
try {
    method.invoke(new Service());
} catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}


=================== 이렇게 수정 ======================
try {
    method.invoke(new Service());
} catch (Exception e) {
}

 

 

- 최종 코드

package chap06.sec15.exam01_annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class PrintAnnotationExample {
	
	public static void main(String[] args) {
		Method[] declaredMethods = Service.class.getDeclaredMethods();
		
		for(Method method : declaredMethods) {
			if(method.isAnnotationPresent(PrintAnnotation.class)) {
				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();
				
				// 메소드 호출
				try {
					method.invoke(new Service());
				} catch (Exception e) {
				}
				System.out.println();
			}
		}
		
	}
}

블록과 블럭 사이에 있는 System.out.println() 이 코드는 줄 내림을 위한 것임.

 

 

 

실행해보자. (ctrl + F11)

 

반응형

'study > JAVA' 카테고리의 다른 글

부모 생성자 호출(super(...))  (0) 2022.02.24
상속(Inheritance) - 클래스 상속  (0) 2022.02.24
Getter와 Setter  (0) 2022.02.18
접근 제한자( Access Modifier)  (0) 2022.02.18
상수(static final)  (0) 2022.02.14

댓글