머리털 나고 처음 보는 개념이라 잘 읽히지도 않고.. 그냥 쓰면서 공부해야 조금이라도 머리 속에 들어올듯.
1. 메타데이터(metadata)
- 응용 프로그램이 처리해야 할 데이터가 아니라, 컴파일&실행 과정에서 코드를 어떻게 컴파일하고 처리할 것 인지를 알려주는 정보.
- 그 코드 자신에 대한 설명을 담은 데이터라고 이해할 수 있다.
- 어노테이션을 메타데이터의 일종이라고 볼 수 있다.
2. 용도
- 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공
- 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보를 제공
- 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공
3. 용도의 예
- @Override 어노테이션의 경우 : 메소드가 오버라이드 된 것을 컴파일러에게 알려주어 컴파일러가 오버라이드 검사를 하게함.
- 빌드 시 자동으로 XML 설정 파일을 생성하기도 함.
- 배포를 위해 JAR 압축 파일을 생성
- 실행 시 클래스의 역할을 정의 하기도 한다.
-> 내 생각에 배포자나 툴 개발자가 라이브러리에 어노테이션을 선언하고, 자유롭게 쓸 수 있도록 제공하는식인듯(?)
4. 사용 방법
// 1. 어노테이션 정의.
@AnnotationName
// 2. 어노테이션은 element를 멤버로 가질 수 있으며,
// 타입으로는 int 등 기본 데이터 타입, String, 열거 타입, Class 타입, 이들의 배열 타입을
// 이용할 수 있다.
@AnnotationName(elementName="값", elementName2=3);
// 3. 어노테이션은 기본 엘리먼트인 value를 가질 수 있다.
@AnnotationName(3);
@AnnotationName("값");
// 4. 기본 엘리먼트 value와 다른 엘리먼트의 값을 동시에 줄 수도 있다.
@AnnotationName(value="값", elementName2="3);
5. 적용 대상
- 어노테이션을 적용 할 수 있는 대상은 java.lang.annotation.ElementType에 정의되어 있다.
- 클래스, 인터페이스, 열거 타입, 필드, 생성자, 메소드, 로컬 변수, 패키지 등에 적용할 수 있다.
- 적용 예)
// 클래스에 적용된 어노테이션
@ClassAnnotation
public class ClassName
{
//필드에 적용된 어노테이션
@FieldAnnotation
String FieldName;
//메소드에 적용된 어노테이션
@MethodAnnotation
bool IsMyName();
}
6. @Target
- 자신이 만든 어노테이션에 사용될 자바 요소를 지정할 수 있다.
// @Target의 기본 엘리멘트 value는 ElementType 배열을 값으로 가진다.
// 이는 어노테이션이 적용될 대상을 복수개로 지정하기 위함이다.
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@AnnotationName
// 이렇게 어노테이션을 적용할 경우,
// 클래스, 필드, 메소드에 어노테이션을 적용할 수 있다.
7. 유지 정책
- 사용 용도에 따라 어노테이션을 어느 범위까지 유지할 것인지 지정해야 한다.
- 소스상에서만, 컴파일된 클래스까지, 런타임 시에도 유지할것인지를 지정해야 한다.
- 이 정보는 java.lang.annotation.RetentionPolicy 열거 상수에 정의 되어 있다.
RetentionPolicy | 설명 |
SOURCE |
소스상에서만 어노테이션 정보 유지. 소스코드 분석 시에만 의미가 있으며, 바이트 코드 파일에는 정보가 남지 않는다. |
CLASS |
바이트 코드 파일까지 어노테이션 정보 유지. 리플렉션을 이용해서 정보를 얻을 수 없다. |
RUNTIME |
바이트 코드 파일까지 어노테이션 정보를 유지하면서 리플렉션을 이용해 런타임 시에 어노테이션 정보를 얻을 수 있다. |
8. 리플렉션
- 런타임 시에 클래스의 메타 정보를 얻는 기능
- 클래스가 갖고 있는 필드, 생성자, 메소드, 어노테이션을 런타임 중에 알아내는 것.
- 우리가 작성하는 어노테이션은 대부분 런타임 시점에 사용하기 위한 용도로 만들어진다.
- 사용 예)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@AnnotationName
- 어노테이션 자체는 아무런 동작을 가지지 않는 메타데이터이지만, 리플렉션을 이용해서 어노테이션의 적용 여부와 엘리먼트 값을 읽고 적절히 처리할 수 있다.
9. 어노테이션 적용 예)
// 1. 어노테이션 정의
package Hyunndy_Toy_Package;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(METHOD)
public @interface PrintAnnotation {
String value() default "-";
int lines() default 15;
}
// 2. 어노테이션 적용 클래스
package Hyunndy_Toy_Package;
public class Service {
@PrintAnnotation
public void Method1()
{
System.out.println("실행 내용1");
}
@PrintAnnotation("*")
public void Method2()
{
System.out.println("실행 내용2");
}
@PrintAnnotation(value="#", lines=20)
public void Method3()
{
System.out.println("실행 내용3");
}
}
// 3. Main()이 존재하는 Class에서 리플렉션을 이용해 어노테이션 정보를 읽고 엘리먼트 값, 메소드를 호출.
package Hyunndy_Toy_Package;
import java.lang.reflect.*;
public class Hyunndy
{
public static void main(String[] args)
{
//Service 클래스로 부터 메소드 정보를 얻음.
Method[] declaredMethods = Service.class.getDeclaredMethods(); //[리플렉션] Service 클래스에 선언 된 메소드 얻기
for(Method method : declaredMethods)
{
//[리플렉션] PrintAnnotation 어노테이션이 적용되었는지 확인.
if(method.isAnnotationPresent(PrintAnnotation.class))
{
//[리플렉션] 어노테이션 객체 얻어오기.
PrintAnnotation p = method.getAnnotation(PrintAnnotation.class);
System.out.println("[" + method.getName() + "]");
for(int i=0; i<p.lines(); i++)
{
System.out.print(p.value());
}
System.out.println();
try
{
method.invoke(new Service());
}
catch(Exception e) {}
System.out.println();
}
}
}
}
'Deperecated > JAVA' 카테고리의 다른 글
JAVA - 익명 구현 객체, 람다식 (0) | 2020.01.09 |
---|---|
JAVA - 인터페이스 (0) | 2020.01.09 |
JAVA 기본서 공부 5 - 클래스 (0) | 2020.01.05 |
JAVA - 열거 타입 (0) | 2020.01.04 |
JAVA - 향상된 for문 (0) | 2020.01.04 |