Java lang

[이것이 자바다] 자바 어노테이션 공부 정리

Razelo 2020. 12. 20. 22:01
package sec15.exam01_annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD}) //적용대상은 메소드이다. 
@Retention(RetentionPolicy.RUNTIME) 
public @interface PrintAnnotation {
	//괄호 열고 닫고를 꼭 붙인다. 메소드는 아니다.
	String value() default "-";  
	int number() default 15;
}
package sec15.exam01_annotation;

public class Service {
	@PrintAnnotation
	public void method1() {
		System.out.println("실행 내용1");
	}
	@PrintAnnotation("*") //value의 값만 바꾸자. 
	public void method2() {
		System.out.println("실행 내용2");
	}
	@PrintAnnotation(value = "#",number = 20) //둘다 바꾼다. 
	public void method3() {
		System.out.println("실행 내용3");
	}
}

 

package sec15.exam01_annotation;

import java.lang.reflect.*; //동적으로 클래스의 메타정보를 조사하는 게 리플렉트임. 관련 패키지입니다. 

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() + ":");
//				System.out.println("value="+printAnnotation.value());
//				System.out.println("number="+printAnnotation.number());
//				System.out.println();
				
				//메소드 이름 출력
				System.out.println("["+method.getName()+"]");
				
				//구분선 출력
				for(int i = 0;i<printAnnotation.number();i++) {
					System.out.print(printAnnotation.value());
				}
				System.out.println();
				
				//메소드 호출 
				//Service service = new Service(); service.method1(); 와 똑같다.
				try {
					method.invoke(new Service());
				} catch (Exception e) {} 
				System.out.println();
				
			}
		}

	}

}

 

package Annotation;

/*
<어노테이션이란>
프로그램에게 추가적인 정보를 제공하주는 메타데이터이다. 

<어노테이션 용도>
컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공
소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공
실행시(런타임시) 특정기능을 실행하도록 정보를 제공 

<어노테이션의 엘리먼트 멤버>
어노테이션을 코드에 적용할 때 외부의 값을 입력받을 수 있도록 하는 역할 
엘리먼트의 타입은 기본타입과 참조타입을 모두 사용할 수 있다. 

<기본 엘리먼트 value 엘리먼트 >
-> 어노테이션을 적용할 때 엘리먼트 명을 생략가능하다. 
-> 두개 이상의 속성을 기술할 때는 value = 값 형태로 기술한다. 

<어노테이션 적용 대상> 
코드 상에서 어노테이션을 적용할 수 있는 대상
java.lang.annotation.ElementType 열거 상수로 정의되어 있음. 

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

<어노테이션 적용 대상 지정 방법> 
@Target 어노테이션으로 적용 대상 지정 
@Target 의 기본 엘리먼트인 value 의 타입은 ElementType 배열임. 

<어노테이션 유지 정책>
어노테이션 적용 코드가 유지되는 시점을 지정하는 것
java.lang.annotation.RetentionPolicy 열거 상수로 정의되어 있음.
SOURCE	소스상에서만 어노테이션 정보를 유지한다. 소스 코드를 분석할 때만 의미가 있으며, 바이트 코드 파일에는 정보가 남지 않는다. 
CLASS	바이트 코드 파일까지 어노테이션 정보를 유지한다. 하지만 리플렉션을 이용해서 어노테이션 정보를 얻을 수는 없다. 
RUNTIME 바이트 코드 파일까지(~.class) 어노테이션 정보를 유지하면서 리플렉션을 이용해서 런타임에 어노테이션 정보를 얻을 수 있다. 

리플렉션: 런타임에 클래스의 메타 정보(클래스의 이름...필드의 정보... 생성자...)를 얻는 기능
클래스가 가지고 있는 필드, 생성자, 메소드, 어노테이션의 정보를 얻을 수 있다.
런타임시에 어노테이션 정보를 얻을려면 유지 정책을 RUNTIME으로 설정해야함. 

<유지 정책 지정 방법>
@Retention 어노테이션으로 유지 정책을 지정한다. 
@Retention의 기본 엘리먼트인 value의 타입은 RetentionPolicy이다. 

<런타임시에 어노테이션 정보 사용하기 >
클래스에 적용된 어노테이션 정보 얻기
클래스.class 의 어노테이션정보를 얻는 메소드를 이용 

필드, 생성자,메소드에 적용된 어노테이션 정보 얻기
클래스.class 의 다음 메소드르 이용해서
java.lang.reflect 패키지의 Field,Constructor,Method 클래스의 배열을 얻어냄. 

리턴타임				메소드명					설명
Field[]				getFields()				필드 정보를 Field 배열로 리턴
Constructor[] 		getConstructors()		생성자 정보를 Constructor 배열로 리턴
Method[]			getDeclareMethods()		메소드 정보를 Method 배열로 리턴 

어노테이션 정보를 얻기 위한 메소드 
1. boolean    			isAnnotationPresent(Class <? extends Annotation> annotationClass)
2. Annotation 			getAnnotation(Class<T> annotationClass)
3. Annotation[]  		getAnnotations()
4. Annotation[] 		getDeclaredAnnotations()

1. 지정한 어노테이션이 적용되었는지 여부, Class 에서 호출했을 경우 상위 클래스에 적용된 경우에도 true를 리턴한다. 
2. 지정한 어노테이션이 적용되어 있으면 어노테이션을 리턴하고 그렇지 않다면 null을 리턴한다. Class 에서 호출했을 경우 상위 클래스에 적용된 경우에도 어노테이션을 리턴한다. 
3. 적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된  어노테이션도 모두 포함한다. 적용된 어노테이션이 없을 경우 길이가 0 인 배열을 리턴한다. 
4. 직접 적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 어노테이션은 포함되지 않는다. 






*/

 

반응형