annotation

Study/JAVA 2012. 8. 3. 17:00

nnotations이란 무엇인가 ?

 

- JCP의 5.0(JDK1.5)스펙의 일부인 JSR-175은 자바의 "metadata facility(메타데이터 기능)"을 제안한 것이다. 아마 더 적절한 용어는 metacoding(메타코딩)일 것이다:Annotation은 자바 클래스와 메소드,필드(변수)들을 기술하고 보다 상세하게 설명해주는 코드의 일부분인다. Annotation은 특별한 인터페이스로 구현되어지며 패키지화되고 컴파일 되며 다른 클래스들처럼 import될 수 있다.

 

Markers

 

- Marker Annotation은 당신이 (소스를 읽거나 작성할 때) 필요한 모든 정보를 제공해주는 Annotation이 어디에 있는지 알려주는 간단한 form이다.

- 예를 들어 어떤 가상의 OODBMS가 코드를 마킹하기 위해 어떻게 Annotation을 사용할지를 생각해보자. 디자이너가 자신들의 persistence 메커니즘을 자바의 직렬화 기능에 전적으로 의존적이지 않게 만들기를 원한다고 했으므로 Serializable 인터페이스와 transient 키워드를 사용하는 것을 피하기를 원했다. 마커들의 두 예제는 그 클래스가 persistent 하다는 것을 가르키며서 다른 하나는 어떤 필드가 transient하다는 것을 마킹할 것이다.

 

import oodbms.annotation.Persistable;
import oodbms.annotation.Transient;

@Persistable public class Foo {

    private String field;
    @Transient private String tmpField;
}

 

- 이렇게 하면 OODBMS는 트랜잭션의 맥락에서 사용되는 클래스를 persistent 한 것으로 인식할 수 있으며 적절하게 이 클래스를 저장하고 업데이트 할 수 있을 것이다. 또한  @Transient라고 마킹된 임시 필드 값을 무시하므로 클래스의 원래 용도를 충족시켜 줄 수 있을 것이다.

 

Single value


- 대부분의 annotation은 파라미터들을 필요로 한다. 그러나 하나만을 필요로 하는 특별한 경우 annotation 스펙은 shorthand(속기)를 제공한다. 우리가 persistent 클래스의 버젼 번호들을 선언하고 싶은 경우를 생각해보자. 여기 한가지 방법이 있다.

 

Import oodbms.annotation.Persistable;
Import oodbms.annotation.Version;

@Persistable 
@Version ("1.0.0")
public class Foo { }

 

- 일반적으로 단일 파라미터 annotation은 다음과 같은 형식을 취한다. @Annotation(param-value). 이는  @Annotation(value=param-value) 에 대해 보다 더 컴팩트한 표현이다.

 

Normal annotations

 

- 대개의 경우 당신은 코드들에 대해서 단지 하나의 속성 이상의 보다 더 구조화된 정보를 제공하고 싶을 것이다. 이런 경우 annotations은 하나 혹은 그 이상의 이름-값 쌍을 정의하게 해준다. 값들은 자바의 기본 자료형들 (int값들, String값들, double값들, boolean 값들, 등등의)이나 다른 annotation들이 될것이다.

- 이는 당신이 타입 안정성을 유지하면서 매우 복잡한 구조를 생성하게 할것이다. 이는 전통적인 Doclet 태그들에 대해 새로운 annotation이 갖는 혜택중 하나이다. 버젼 번호를 부여하는 예제를 다시 살펴보자 우리는 그 정보들을 보다 더 구조화 하고 싶을 것이다.

 

@Persistable
@Version(major=1, minor=0, micro=0)
public class Foo { }

 

- 컴파일러와 IntelliJ IDEA 4.0 나 Eclipse 3.1 (in beta)같은 JDK 1.5를 지원하는 syntax-aware IDE는 이 새로운 Version annotation의 적절한 사용을 즉시 인식할것이다.예를 들어 이중 한 필드에 대한 오타를 인식한다는 것이다.

 

 

Arrays


- annotation은 배열구문( {}를 이용하여 배열을 표현하는 것을 상기하라 )을 이용하여 다중 값을 취하는 필드들을 가질 수 있다. 예를 들어 우리가 Javadoc 의 작성자 필드들을 교체하고자 한다면 다음과 같이 다중 값을 허용할 수 있다.

 

@Authors({
    @Author("Jane Doe")
    @Author("John Doe")
})

 

- 배열 안에 배열을 집어넣을 수도 있고 배열안의 복합된 annotation을 집어 넣을 수도 있다. 만약 메타 코드들을 annotation으로 표현할 수 없는 경우 아마 이것으로 많은 일을 하려고 할 것이다. 이 구문은 매우 강력하다.

-- boil down to ...결국[요컨대] ···으로 되다

 

Declaring Your Own Annotations (자신만의 고유의 Annotations을 선언하기)

 

- annotation은 이름을 가지고 타입이 지정되어 혹은 내장된 열거형으로 또는 필요하다면 인터페이스처럼 코드 없이 struct-like 폼안에 선언되어진다. annotation은 궁극적으로는 메소드, 필드, 혹은 그들이 annotate할 타입들을 위한 여분의 JVM 바이트코드 attribute로 변환될 순수한 데이터 구조이다

 

public @interface HelloAnno {
    enum Scope { LOCAL, WORLD }
    String name();
    Scope scope();
}

 

위의 선언에서 annotation은 다른 annotation에의 의해서 참조 되어질 수도 있다.

 

import oodbms.annotation.Version;
 
public @interface HelloAnno {
    enum Scope { LOCAL, WORLD }
    String name();
    Scope scope();
    Version version();
}

 

그리고 기본값도 가질 수 있다.

import oodbms.annotation.Version;
 
public @interface HelloAnno {
    enum Scope { LOCAL, WORLD }
    String name() default "Foo";
    Scope scope() default Scope.LOCAL;
    Version version();
}

 

위의 정의는 다음과 같은 두가지 방법으로 정의 될수 있다

@HelloAnno(version=@Version(major=1,minor=0,micro=0))

기본값을 가지는 장점으로 다음과 같이 명시적인 값을 세팅할수 있다

@HelloAnno(name="Bar", scope=Scope.WORLD, 
    
version=@Version(major=1,minor=0,micro=0))

선언 기법을 하나만 더 보자. 단일 값을 가지는 annotation을 위해 컴파일러는 단일 필드는 value라는 이름을 가질 것이라고 가정할 것이다. 다음처럼

 

public @interface HelloAnno {
    String value() default "world";
}

// usage: value gets assigned "world" 사용법 : value는 "world"란 값을 할당 받을 것이다
@HelloAnno("world");

// also valid 이렇게 하는 것도 가능하다.
@HelloAnno(value="world")

// and this works too, thanks to the default! 이것도 동작한다.기본값을 취할것이므로 
@HelloAnno


C'mon, Arthur! Get meta with me!

 

- Annotation 선언들은 그들만의 Annotation을 가질수 있다. 저자는 이것을 메타 코딩의 메타라고 부르기로 했다. 스펙에서는 이것들을 "Meta Attributes"라고 부른다. 예를 들어 @Target annotation 은 자바의 어떤 요소가 당신의 애플리케이션에서 수정될수 있는지를 정의하고 있다. @Target(ElementType.TYPE)은 자바의 열거형, 클래스, 인터페이스만 수정할 수 있도록 제한하고 있다. @Target(ElementType.CONSTRUCTOR)은 생성자만 수정할 수 있다. 머 대충 이런식이다

- @RetentionPolicy annotation 는 컴파일러에게 annotation으로 무엇을 할 수 있는지를 알려준다: SOURCE는 이것을 제거하며 클래스 파일안에 내장된 CLASS와 RUNTIME은  리플렉션을 통해 이를 가능하게 해준다.

- 위의 예를 든 OODBMS는 JVM에 올라가면 바이트코드를 볼수 있는 매우 영리한 클래스 로더를 가지고 있어서 우리는 리플렉션을 쓸 필요성을 못느낀다. 우리의 Version annotation은 다음과 같을 것이다

 

package oodbms.annotation;

import java.lang.annotation.*;

@RetentionPolicy(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Version {
    int major();
    int minor() default 0;
    int micro() default 0;
}

 

JDK 5.0없이 Annotation 하기

- 지금까지 살펴본 이 Annotation기능에 대해서 여러분들은 아마 흥미를 느꼈을 것이다. 그러나 만약 여러분이 JDK5.0을 설치하지 않았다면 어떻게  이 기능들을 여러분의 프로그램에 사용할 수 있을 것인가.

 

XDoclet

- XDoclet과  XDoclet의 AOP(attribute-oriented programming) 구현은 다른 책들에서 많이 다루어진 주제이기 때문에 저자는 여기서 비교를 목적 이상의 개요설명은 하지 않을 것이다.

- XDoclet은 코드들을 annotating하기 윈한 Javadoc 태그 기반의 접근이다. Xdoclet 툴을 위한 플러그인들은 새로운 기능들을 제공한다. 메타데이터 구조는 JDK1.5보다 더 단조롭고하고 덜 객체지향적이다. 만약 당신의 IDE가 Javadoc 태그들은 인식하고 모르는 것들에 대해서 반전해서 표시한다면(IntelliJ처럼) 당신의 IDE에게 새로운 태그들에 대해서 알려줘야 한다. 또한 만약 문자열 대신에 integer값을 넘겨줘야 한다면 XDoclet을 도입하기 전까지는 고생좀 할 것이다. 게다가 이런 문제는 발생하기 전까지는 예측하기도 어렵다는 것이다.

- 반면에 XDoclet은 그것을 어떻게 하면 잘 사용하는가에 대한 지식이 있는 누군가가 있는 프로젝트에 적용되어 왔다. XDoclet은 자바 언어의 일부가 되기 보다는 오히려 직접 교류한다는(대등한 위치에 있다는) 장점을 가지고 있다:자바언어와 XDoclet은 서로 독립적이며 서로 다른 속도로 발전하고 있다.

-  만약 Sun이 XDoclet을 적용하다면 자바코드를 다루는 기존의 라이브러리와 UI 툴은 여전히 그대로 남아있을 수 있다.

 

Commons attributes
- 아파치의 자카르타 프로젝트는 Commons Attributes를 제공한다.(Commons 에는 로깅, 데이터 베이스 풀링, 콜렉션 같은 범용 기능을 제공하는 많은 API가 있다. 역자주 맞을라나 ?! ). 이 패키지는 JDK5.0과 매우 유사한 기능들을 이전 버젼의 JDK를 쓰는 사용자들을 위해 제공하고 있다.

- 오로지 JDK5.0가 @를 쓰는 대신 @@를 쓴다는 구문의 차이와 언어자체에 포함된게 아니라 Javadoc에 이식되어 있다는 드런 차이점밖에는 존재하지 않는다. Attributes 는 클래스로 구현되어 있으므로 post-processing 타임에 높은 수준의 타입 안정성을 보장 받을 수 있다.


우리의 예제에서 Version 은 다음과 같이 바꿀 수 있다.


public class Version {
    public Version() { }

    public int getMajor() {
        return major;
    }

    public void setMajor(int major) {
        this.major = major;
    }

    public int getMinor() {
        return minor;
    }

    public void setMinor(int minor) {
        this.minor = minor;
    }

    public int getMicro() {
        return micro;
    }

    public void setMicro(int micro) {
  this.micro = micro;
    }

    private int major;
    private int minor;
    private int micro;
}

그리고 다음과 같이 사용될 수 있다.

/**
 * @Persistable
 * @@Version(major=1,minor=0,micro=0)
 */
public class Foo { }


- Commons Attributes 는 attribute  ANT나 MAVEN에 통합되어 있는 컴파일러를 제공하므로 annotation을 포함한 최종 자바 클래스 화일들을 생성할 수 있다. 또한 클래스로부터 annotation을 읽어낼 수 있는 실시간 인터페이스도 제공한다.

- Commons Attributes가 가장 잘 만들어진 대안이며 JDK5.0으로 이동이 수월하다는 것도 큰 장점이다.

 

 

http://blog.naver.com/PostView.nhn?blogId=neo_nebula&logNo=60008253953&redirect=Dlog&widgetTypeCall=true

[출처] annotation 이란?|작성자 neo_nebula

 

Posted by 코딩하는 야구쟁이
,