늦은 프로그래밍 이야기

Annotation 본문

내일배움캠프/Spring

Annotation

한정규 2022. 12. 21. 00:39

Annotation이란?

  • 사전적 의미로 주석이라는 뜻.
  • 자바에서는 코드 사이에 주석처럼 쓰여서 특별한 의미, 기능을 수행하도록 하는 기술.
  • 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta data : 데이터를 위한 데이터)

용도

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

사용하는 순서

  • 어노테이션 정의
  • 클래스에 어노테이션을 배치
  • 코드가 실행되는 중에 Reflection을 이용하여 추가정보를 획득하여 기능 실시

Reflection이란?

  • 프로그램이 실행 중에 자신의 구조와 동작을 검사하고, 조사하고, 수정하는 것
  • 프로그래머가 데이터를 보여주고, 다른 포맷의 데이터를 처리하고, 통신을 위해 Serialization(직렬화)를 수행하고, bundling을 하기 위해 일반 소프트웨어 라이브러리를 만들도록 도와준다.
  • Java와 같은 객체 지향 프로그래밍 언어에서 Reflection을 사용하면 컴파일 타임에 인터페이스, 필드, 메소드의 이름을 알지 못해도 실행 중에 클래스, 인터페이스, 필드 및 메소드에 접근할 수 있다.
  • 새로운 객체의 인스턴스화 및 메소드 호출을 허용한다.
  • Java와 같은 객체 지향 프로그래밍 언어에서 Reflection을 사용하여 멤버 접근 가능성 규칙을 무시할 수 있다.
  • Spring에서 BeanFactory라는 Container에서 객체가 호출되면 객체의 인스턴스를 생성하게 되는데 이때 필요하게 된다. 즉, 프레임워크에서 유연성 있는 동작을 위해 쓰인다.
  • Annotation 자체는 아무런 동작을 가지지 않는 단순한 표식일 뿐이지만, Reflection을 이용하면 Annotation의 적용 여부와 엘리먼트 값을 읽고 처리할 수 있다.
  • Class에 적용된 Annotataion 정보를 읽으려면 java.lang.Class를 이용하고 필드, 생성자, Method에 적용된 Annotation 정보를 읽으려면 Class의 메소드를 통해 java.lang.reflect 패키지의 배열을 얻어야 한다.
    • Class.forName(), getName(), getModifier(), getFields(), getPackage() 등 여러 메소드로 정보를 얻을 수 있다.
  • Reflection을 이용하면 Annotation 지정만으로도 원하는 클래스를 주입할 수 있다.

어노테이션 정의

어노테이션을 적용할 때는 어노테이션이 어디에 적용되며 언제까지 어노테이션 소스가 유지될 것인지를 설정하여야 하는데 소스코드에는 다음과 같이 어노테이션을 정의해 주면 된다.

@Target({ElementType.[적용대상]})
@Retention(RetentionPolicy.[정보유지되는 대상])
public @interface [어노테이션명] {
	public 타입 elementName() [default 값]
	...
}

@Target에는 어떠한 값에 어노테이션을 적용할 것인지 나타낼 수 있다.

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

@Retention에는 어노테이션 값들을 언제까지 유지할 것인지 값을 입력하는데 각 값이 가지는 의미는 다음 표와 같다. 보통 어노테이션은 Runtime시에 많이 사용하므로 대부분의 어노테이션의 Retention 값은 RUNTIME으로 되어있다.

 

RetentionPolicy 열거 상수 설명
SOURCE 소스상에서만 어노테이션 정보를 유지한다. 소스코드를 분석할 때만 의미가 있으며, 바이트 코드 파일에는 정보가 남지 않는다.
CLASS 바이트 코드 파일까지 어노테이션 정보를 유지한다. 하지만 리플렉션을 이용해서 어노테이션 정보를 얻을 수는 없다.
RUNTIME 바이트 코드 파일까지 어노테이션 정보를 유지하면서 리플렉션을 이용해서 런타임에 어노테이션 정보를 얻을 수 있다.

어노테이션의 배치 및 사용

어노테이션의 사용은 클래스를 참고하는 소스의 흐름상에서 Reflection을 사용하는 방법을 통해서 어노테이션 값을 활용하도록 한다.

 

리턴타입 메소드명(매개변수) 설명
Field[] getFields() 필드 정보를 Field 배열로 리턴
Constructor[] getConstructor() 생성자 정보를 Constructor 배열로 리턴
Method[] getDeclaredMethod() 메소드 정보를 Method 배열로 리턴

다음 코드는 MyMain 클래스가 MyService 클래스의 메소드에 MyAnnotiation 어노테이션 설정이 있는지 확인하고 각 메소드에 설정된 어노테이션에 삽입된 값에 따라 특정값을 일정한 숫자만큼 출력하는 예제이다.

 

[MyAnnotation.java]

package myannotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

 

[MyService.java]

package myannotation;

public class MyService {
	@MyAnnotation
	public void method1() {
		System.out.println("실행내용1");
	}
	
	@MyAnnotation("*")
	public avoid method2() {
		System.out.println("실행내용2");
	}

	@MyAnnotation(value = "*", number = 20)
	public void method3() {
		System.out.println("실행내용3");
	}
}

 

[MyMain.java]

improt java.lang.reflect.Method;

public class MyMain {
	public static void main(String[] args) {
		Method[] methodList = MyService.class.getMethods();

		for(Method m : methodList) {
			if (m.isAnnotationPresent(MyAnnotation.class)) {
				System.out.println(m.getName());
				MyAnnotation annotation = m.getDeclaredAnnotation(MyAnnotation.class);
			
				String value = annotation.value();
				int number = annotation.number();
				for (int i = 0; i < number; i++) {
					System.out.print(value);
				}
				System.out.println();
			}
		}
	}
}

결과값

더보기

method2

***************

method3

********************

method1

---------------

필드, 생성자, 메소드에 적용된 어노테이션 정보는 .class로부터 얻을 수 있다.

 

어노테이션 정보를 얻기 위한 메소드

리턴타입 메소드명(매개변수)
boolean isAnnotationaPresent(Class<? Extends Annotation> annotationClass)
지정한 어노테이션이 적용되었는지 여부. Class에서 호출했을 경우 상위 클래스에 적용된 경우에도 true를 리턴한다.
Annotation getAnnotation(Class<T> annotationClass)
지정한 어노테이션이 적용되어 있으면 어노테이션을 리턴하고 그렇지 않다면 null을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 경우에도 어노테이션을 리턴한다.
Annotation[] getAnnotation()
적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 어노테이션도 모두 포함한다. 적용된 어노테이션이 없을 경우 길이가 0인 배열을 리턴한다.
Annotation[] getDeclaredAnnotation()
직접 적용된 모든 어노테이션을 리턴한다. Class에서 호출했을 경우 상위 클래스에 적용된 어노테이션은 포함되지 않는다.

출처 : Java에서 어노테이션(Annotation) 이란 무엇인가에 대해 알아보자.

 

Java에서 어노테이션(Annotation) 이란 무엇인가에 대해 알아보자.

자바에서 어노테이션이라는 기술이 스프링 프레임워크상에서 자주 쓰이지만 이 기술에 대해 자세히 알아보지도 않고 IT에 몸담고 있는 5년간 대충 아는정도에 밖에 그치지 못하고 있다. 이러한

honeyinfo7.tistory.com


 

'내일배움캠프 > Spring' 카테고리의 다른 글

IoC 컨테이너  (0) 2022.12.21
DI (의존성 주입)  (0) 2022.12.21
UnsatisfiedDependencyException 에러 해결  (0) 2022.12.16
Spring MVC  (0) 2022.12.07
JPA  (0) 2022.12.06
Comments