1. JAVA Annotation이란?

- Java Annotation은 자바5(JEE5)부터 제공되기 시작한 문법 요소로서 @를 이용한 주석이다.

- 자바에서 사용하는 "//, /**/"와  같은 주석과는 다른 의미로, 클래스나, 멤버 변수, 멤버 메서드, 지역 변수, 매개 변수 등 구성요소에 '부착'되는 주석입니다.

@customAnnotation

public class CustomAnnotationSample 

{

...

}


- CustomAnnotationSample이라는 클래스에 @customAnnotation이라는 Annotaion을 사용했다. 단순히 CustomAnnotationSample  Class에 customAnnotation이라는 라벨를 달았다고만 생각하면 된다. Annotaion을 달았다고 어떤 기능이 동작하거나 생기는건 아니다. 제품들에 바코드가 붙었다고 무슨 기능을 하지 않는 것처럼 바코드 리더로 찍어보기 전에는 아무런 의미가 없다. 바코드를 읽는 바코드 리더기와 같이 Annotaion 부착된 구성요소는 자바의 Reflection 을 이용하여 기능을 부여할 수 있다.

2. Annotaion 사용 용도

- 데이터를 문서화하거나, 컴파일 타임이나 런타임시에 원하는 동작을 수행할 수 있도록 하는 데 사용

- 해당 엘리먼트에 대해 생성된 자바 바이트코드를 변경하지 추가 수식자 (modifier)라 할 수 있음

- 어노테이션이 나오기 전까지 메타데이터는 프로퍼티 파일과 XML파일을 활용


3. Annotation의 장점

- 코드의 가독성 증대 : 관련 코드 곁에 메타데이터를 설정할 수 있으므로 코드의 가독성 증대

- 개발 효율성 증대 : 복잡한 XML 스키마를 파악하지 않아도 되며, 개발시 개발 툴과 컴파일러의 도움을 받을 수 있으므로 개발 효율성이 증대

- 별도의 파서를 적용하지 않고도 간단히 런타임 시에 활용할 수 있는 편리함

- JUnit, Framework, Permission Module 에서 사용


4. Annotation의 단점

- Annotaion 처리시 리플렉션을 통해 해당 클래스를 분석해야 하는 오버헤드 발생

- XML 파일을 이용하는 방법도 오버헤드가 있으므로, 경우에 따라서 Annotaion이 더 빠를 수도 있음.

- Annotaion은 모듈이나 어플리케이션 전반적인 메타데이터를 설정할 수 없음 : Annotaion의 범위는 클래스나 패키지 레벨로 한정되기 때문에 여러 클래스에 걸친 공통적인 설정이나 모듈레벨 설정이 어렵움, 웹 어플리케이션 개발시 서블릿 필터나, 인터셉터를 이용해서 문제 해결이 가능함.



5. Annotaion 종류

Annotaion은 메타데이터 저장을 위해 클래스처럼 멤버의 개수에 따라 Marker/Single-Value/Full Annotaion으로 분류

1) Marker Annotaion 

 - 멤버 변수가 없으며, 단순히 표식으로서 사용되는 Annotaion이다. 컴파일러에게 어떤 의미를 전달

 - @AnnotationName

2) Single-Value Annotaion 

 - 멤버로 단일 변수만 갖는 Annotaion. 단일 변수 밖에 없기 때문에 (값)만을 명시하여 데이터를 전달

 - @AnnotationName(elementValue)

3) Full Annotaion 

 - 멤버로 둘 이상의 변수를 갖는 Annotaion으로, 데이터를 (값=쌍)의 형태로 전달

 - @AnnotationName(element=value, element=value, ...)


6. Built-In Annotaion

1) Standard Annotations

JAVA에서 지원하는 Annotaion으로 @Override, @Deprecated, @SuppressWarning등이 있다.

(1) @Override

    - 메소드에 대해서만 사용

- 해당 메소드가 부모 클래스에 있는 메소드를 오버라이드 했다는 것을 명시적으로 선언

- 만일 자식 클래스에 부모 클래스에 해당하는 메소드가 없으면 컴파일러가 인지하여 에러 발생 시킴


(2) @Deprecated

- Marker Annotaion으로 클래스, 메소드, 필드 등에 선언하며 지정한 요소가 더이상 사용되지 않음을 의미

- 컴파일러는 deprecated된 메소드나 클래스 혹은 변수를 사용할 때마다 경고를 발생


(3) @SuppressWarnings

- 클래스, 메소드, 필드의 선언, 컴파일러의 경고를 제거(이 부분에 대해서 경고문을 출력하지 말라는 의미)

- 참고로 다른 Annotation 과 다르게 속성값을 지정해 줄 수도 있다. 

- all, deprecation, unchecked, fallthrough, path, serial, finally 등의 금지 옵션이 있음.

 ex) @SuppressWarnings("deprecation"), @SuppressWarnings("serial")



2) Custom Annotations

 - 개발자가 정의하는 Annotaion으로 class 형태로 만들어짐

 - Annotaion 선언은 @interface 로 한다.

 - 이름 앞에 '@' 문자가 오는 것 외에는 기본적으로 인터페이스를 선언하는 것과 동일(메소드들의 내용은 없고 형태만 선언)

 - default 가 찍히지 않은 메소드는 필수로 입력해야 함

1. Custom Annotations 정의

// 메소드와 클래스가 여전히 작업중임을 나타내기 위해 정의한 Marker Annotaion

public @interface customAnnotation{}

       - Annotaion 정의 파일을 컴파일하고, 이파일을 클래스패스에서 참조할 수 있으면 다른 소스코드상에서 Annotaion을 사용 할 수 있다.

  

2. 멤버 추가하기

  - Annotaion 유형은 멤버 변수를 가질 수 있으며, 이 변수들 컴파일시 또는 런타임에 메타데이터로서 사용될 수 있다.

    이렇게 정의를 하면 자동으로 accessor와 mutator를 제공해준다.

 public @interface customAnnotation{

public int value();

}

- 정의한 Annotaion을 다음과 같이 사용한다.

@customAnnotation(vale = 1)

public void customAnnotationSample(){

// ..

}

- 단일 멤버를 갖을 경우에만 위와 같이 사용할 수 있다.

3. 디폴트 값 설정하기

public @interface customAnnotation{

public int value();

public String desc() default "My Custom Annotation"

}

- 디폴트값을 사용한 예는 다음과 같다.

@customAnnotation(vale = 1)

public void customAnnotationSample(){

// ..

}

3) Meta-Annotations

(1) @Target

 - 어노테이션을 정의 시 어노테이션이 사용 가능한 대상을 지정

 - ElementType의 상수로 정의

- ANNOTATION_TYPE : Annotaion 형

- CONSTRUCTOR : 생성자

- FIELD : enum 상수를 포함한 필드(멤버변수)

- LOCAL_VARIABLE : 지역변수

- METHOD : 메소드

- PACKAGE : 패키지

- PARAMETER : 매개변수

- TYPE : 클래스, 인터페이스(어노테이션 형 포함), 열거형

@Target({ElementType.TYPE,

ElementType.METHOD,

ElementType.CONSTRUCTOR,

ElementType.ANNOTATION_TYPE})

public @interface customAnnotation{

public int value();

public String desc() default "My Custom Annotation";

}

(2) @Retention

 - Annotaion정보의 유지 범위를 설정, JVM이 어떻게 사용자 어노테이션을 다루어야 하는지를 서술

 - RetentionPolicy의 상수로 정의

- SOURCE : Annotaion 정보를 클래스 파일에 저장되지 않고 소스를 처리하는 도구에서만 사용.

- CLASS : Annotaion 정보를 컴파일러는 클래스 파일에 저장하지만 VM에서는 읽지 않고 버려짐.

- RUNTIME : Annotaion 정보를 컴파일러는 클래스 파일에 저장하고, VM에서 저장된 정보를 읽음.

@Retention(RetentionPolicy.RUNTIME)

public @interface customAnnotation{

public int value();

public String desc() default "My Custom Annotation"

}  

(3) @Documented : @Documented 해당 어노테이션을 Javadoc에 포함

(4) @Inherited :서브 클래스가 부모 어노테이션을 상속받도록 함

7. Annotation 접근

 - 실행중인 프로그램에서 Annotation에 접근하는 방법을 알아보자.

 - 인터페이스 java.lang.reflect.AnnotateElement를 통해서 실행중인 Annotation에 접근 할 수 있다.

 - boolean isAnnotationPresent(Class<? extends Annotation> annotationType)

- Annotation 존재 여부를 반환한다.

- Annotation이 존재하면 true, 존재하지 않으면 false 반환

 - <T extends Annotation> T getAnnotation(Class<T> annotationType)

- Annotation을 반환

 - Annotation[] getAnnotations()

- 존재하는 모든 Annotation들을 반환 (private 제외)

 - Annotation[] getDeclaredAnnotations()

- 존재하는 모든 Annotation들을 반환 (private 포함)

앞에서 만든 Annotaion 값 확인해보자

import java.lang.reflect.Method;



@customAnnotation(value=0)

public class CustomAnnotationSample 

{

    @customAnnotation(value=1)

    public static void main(String[] args) {

    CustomAnnotationSample customAnnotationSample = new CustomAnnotationSample();

    customAnnotationSample.checkAnnotations(CustomAnnotationSample.class);

    }

 

    @customAnnotation(value=2)

    public void customAnnotation1() {

    }

    @customAnnotation(value=3, desc="My Second Custom Annotation")

    public void customAnnotation2() {

    }

    @customAnnotation(value=4, desc="My Third Custom Annotation")

    public void customAnnotation3() {

    }

 

    @SuppressWarnings({ "rawtypes", "unchecked" })

public void checkAnnotations(Class customAnnotationSampleClass){

    customAnnotation annotation = null;

    if(customAnnotationSampleClass.isAnnotationPresent(customAnnotation.class))

    {    

    annotation = (customAnnotation) customAnnotationSampleClass.getAnnotation(customAnnotation.class);

    int value = annotation.value();

            String desc = annotation.desc();

            System.out.println(customAnnotationSampleClass.getSimpleName() + " Class : value=" + value + " desc=" + desc);

    }

        Method[] methods = customAnnotationSampleClass.getDeclaredMethods();

        for ( Method tempMethod:methods ){

            annotation = tempMethod.getAnnotation(customAnnotation.class);

            if ( annotation != null ){

                int value = annotation.value();

                String desc = annotation.desc();

                System.out.println("This Method "+ tempMethod.getName() + "() : value=" + value + " desc=" + desc);

            } else {

                System.out.println("This Method "+ tempMethod.getName() + "() : Annotation is not exist");

            }

        }

    }

}


결과

CustomAnnotationSample Class : value=0 desc=My Custom Annotation

This Method main() : value=1 desc=My Custom Annotation

This Method customAnnotation1() : value=2 desc=My Custom Annotation

This Method customAnnotation2() : value=3 desc=My Second Custom Annotation

This Method customAnnotation3() : value=4 desc=My Third Custom Annotation

This Method checkAnnotations() : annotation is not exist



8. Annotation Processing Tool

 - Annotation의 소스를 체크하고 컴파일을 처리해줌

 - JDK 5에는 어노테이션을 읽고 이해하는 API가 표준화되어 있지 않아 JDK에 들어있는 썬 고유의 라이브러리를 사용했고, 자바 SE 6에 기본으로 포함되었다.

 - JDK 5에는 APT(Annotation Processing Tool)라는 패키지가 포함되어, JSR 269(JSR 269 Pluggable Annotation Processing API)가 나오기 전까지 임시로 그 역할을 대신했다.

 - Apache Ant에서는 APT에 대응하는 앤트 타스크를 따로 두어 지원하였다. http://ant.apache.org/manual/CoreTasks/apt.html에서 확인할 수 있다

 

참고 사이트

http://wiki.gurubee.net/display/DEVSTUDY/Annotation

http://hiddenviewer.tistory.com/88

http://gubok.tistory.com/167

http://secretroute.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%9D%98%E7%A5%9E-Vol1-Annotation

http://ellehu.com/java/3727

http://piece.tistory.com/7

http://www.nextree.co.kr/p5864/

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

GC 튜닝 절차  (0) 2018.11.09
Java Method Signature  (0) 2017.12.08
VO vs DTO  (0) 2017.01.12
String VS SringBuffer VS StringBuilder  (0) 2016.10.14

+ Recent posts