늦은 프로그래밍 이야기
Annotation 본문
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 |