어노테이션
Annotation
Annotation 이란
- 메타데이터, 한 마디로 데이터의 데이터다
- 어노테이션이 나오기 전까지 메타데이터는 프로퍼티 파일과 XML파일을 활용하였다.
- 어노테이션은 주로 데이터를 문서화하거나, 컴파일 타임이나 런타임시에 원하는 동작을 수행할 수 있도록 하는 데 사용된다.
- 닷넷프레임워크 1.0에서 어트리뷰트라는 기능을 제공하자, 자바에서 어노테이션을 통한 메타데이터 활용 기술을 제공했다.
Annotation의 장점
- 코드의 가독성 증대
- 관련 코드 곁에 메타데이터를 설정할 수 있으므로 코드의 가독성 증대 된다.
- 개발 효율성 증대
- 복잡한 XML 스키마를 파악하지 않아도 되며, 개발시 개발 툴과 컴파일러의 도움을 받을 수 있으므로 개발 효율성이 증대 된다.
- 별도의 파서를 적용하지 않고도 간단히 런타임 시에 활용할 수 있는 편리함이 있다.
- JUnit, Framework, Permission Module 에서 사용
Annotation을 반대하는 사람들의 의견
- 메타정보와 소스의 결합자체를 못마땅하다.
- 메타데이터는 그 자체로 코드에 독립적이어야 하며 한 곳에 모여져서 어플리케이션의 구성을 한눈에 알 수 있어야 바람직하다는 주장.
- 어노테이션은 코드를 이용해서 검증하는게 가능하지만 XML의 DTD나 스키마를 이용하는 검증 방식에 비해서 훨씬 불편하다.
Annotation의 단점
- 어노테이션 처리시 리플렉션을 통해 해당 클래스를 분석해야 하는 오버헤드가 있다.
- XML 파일을 이용하는 방법도 오버헤드가 있으므로, 경우에 따라서 어노테이션이 더 빠를 수도 있음.
- 어노테이션은 모듈이나 어플리케이션 전반적인 메타데이터를 설정할 수 없다.
- 어노테이션의 범위는 클래스나 패키지 레벨로 한정되기 때문에 여러 클래스에 걸친 공통적인 설정이나 모듈레벨 설정이 어렵다.
- 웹 어플리케이션 개발시 서블릿 필터나, 인터셉터를 이용해서 문제 해결이 가능함.
XML과 어노테이션같이 쓰기
- 대부분의 일반적인 웹 어플리케이션에 적합한 방법 이다.
- 어플리케이션 상에서 디자인 타임에 결정되는 부분에 대해서는 어노테이션을 사용하는 것이 좋고,
실제 디플로이 환경에 따라 바뀔 수 있는 부분의 경우 XML을 사용하여 표기하는 것이 좋다.
Annotation 형태
- Marker Annotation
- 이름만 있는 어노테이션
- @AnnotationName
- Single-Element Annotation
- 하나의 원소만을 가지고 있는 어노테이션
- @AnnotationName(elementValue)
- Normal Annotation
- 여러 개의 원소를 갖는 어노테이션
- @AnnotationName(element=value, element=value, ...)
Builtln Annotation
Standard Annotations
- @Deprecated
- 특정 클래스나 인터페이스, 메소드, 필드 등이 앞으로 더이상 사용되지 말아야 한다는 것을 경고하기 위해서 사용.
- 컴파일러는 deprecated된 메소드나 클래스 혹은 변수를 사용할 때마다 경고를 발생시킨다.
- @Override
- 메소드에 대해서만 사용되어야 한다. (클래스, 패키지 선언, 기타 구조체는 안된다.)
- 수퍼클래스에서 메소드를 오버라이드한다는 것을 나타내며, 슈퍼클래스의 메소드를 재정의하지 못하면 컴파일 에러가 발생.
- @SuppressWarning
- 컴파일러에게 경고를 하지 않도록 지시 한다.
- all, deprecation, unchecked, fallthrough, path, serial, finally 등의 금지 옵션이 있다.
Meta-Annotations
- @Target
- 어노테이션을 정의 시 어노테이션이 사용 가능한 대상을 지정한다.
- ElementType의 상수로 정의
ElementType 상수 | 의미 |
---|---|
ANNOTATION_TYPE | 어노테이션 형 |
CONSTRUCTOR | 생성자 |
FIELD | enum 상수를 포함한 필드(멤버변수) |
LOCAL_VARIABLE | 지역변수 |
METHOD | 메소드 |
PACKAGE | 패키지 |
PARAMETER | 매개변수 |
TYPE | 클래스, 인터페이스(어노테이션 형 포함), 열거형 |
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE})
- @Retention
- 어노테이션 정보의 유지 범위를 설정
- RetentionPolicy의 상수로 정의
- @Retention(RetentionPolicy.SOURCE)
RetentionPolicy 상수 | 의미 |
---|---|
SOURCE | 어노테이션 정보를 클래스 파일에 저장되지 않고 소스를 처리하는 도구에서만 사용. |
CLASS | 어노테이션 정보를 컴파일러는 클래스 파일에 저장하지만 VM에서는 읽지 않고 버려짐. |
RUNTIME | 어노테이션 정보를 컴파일러는 클래스 파일에 저장하고, VM에서 저장된 정보를 읽음. |
- @Documented : @Documented 해당 어노테이션을 Javadoc에 포함한다.
- @Inherited 서브 클래스가 부모 어노테이션을 상속받도록 한다.
사용자 정의 Annotation
- 프로그래머가 정의하는 어노테이션으로 class 형태로 만들어진다.
- 어노테이션의 선언은 @interface 로 한다.
- 이름 앞에 '@' 문자가 오는 것 외에는 기본적으로 인터페이스를 선언하는 것과 동일(메소드들의 내용은 없고 형태만 선언)
- default 가 찍히지 않은 메소드는 필수로 입력해야 한다.
@Retention(RetentionPolicy.RUNTIME) public @interface Maker { int num(); String name(); String id(); String date() default "unsigned"; }
@Maker(num=1, name="김정식", id="oramaster") public class UseMaker { /** * class.getAnnotations() 와 같이 어노테이션을 파싱할수 있다.<br/> * 물론 어노테이션 인터페이스에서 @Retention(RetentionPolicy.RUNTIME) 를 선언해 줘야지만 가능하다<br/> * */ public static void main(String args[]) { for (Annotation a: UseMaker.class.getAnnotations()) { System.out.println("Annotation : " + a); } } } 결과 Annotation : @com.oracleclub.sample.annotation.Maker(date=unsigned, num=1, name=김정식, id=oramaster)
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 포함)
간단한 예제
- Junit 의 테스트 케이스 비슷한 예제.
- SimpleTest 어노테이션 생성
SimpleTest.java
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SimpleTest { }
- SimpleTest를 사용하는 테스트 케이스 UseSimpleTest 생성
UseSimpleTest.java
public class UseSimpleTest { @SimpleTest public void test1(){ System.out.println(" # test1 "); } @SimpleTest public void test2() throws Exception{ throw new Exception(" # 에러 발생 "); } @SimpleTest public void test3(){ System.out.println(" # test3 "); } }
- Annotation에 접근해서 테스트 해보자.
RunnerSimpleTest.java
public static void main(String[] args) throws Exception{ RunnerSimpleTest.runner("com.oracleclub.sample.annotation.UseSimpleTest"); } private static void runner(String className) { int pass = 0; int fail = 0; Object testObject = null; try{ testObject = Class.forName(className).newInstance(); }catch(Exception ce){ System.out.println(className+"를 찾을 수 없습니다. "); } for(Method m : testObject.getClass().getMethods()){ if(m.isAnnotationPresent(SimpleTest.class)){ try{ m.invoke(testObject, null); pass++; }catch(Exception e){ System.out.println(m.getName()+" 테스트 실패 : "+e.getCause()); fail++; } } } System.out.println(" # 테스트 종료 -> 성공 : "+pass+", 실패 : "+fail); } //실행결과 # test1 test2 테스트 실패 : java.lang.Exception: # 에러 발생 # test3 # 테스트 종료 -> 성공 : 2, 실패 : 1
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에서 확인할 수 있다.
Reference
- http://www.zdnet.co.kr/builder/dev/java/0,39031622,39163226,00.htm
- http://www.onjava.com/pub/a/onjava/2004/04/21/declarative.html
- http://www.javapassion.com/javaintro/index.html#J2SE_5.0_Annotations
- http://java.sun.com/j2se/1.5.0/docs/guide/apt/index.html
문서에 대하여
- 작성일자 : 김정식
- 작성자 : 2008년 10월 31일
- 이 문서는 오라클클럽 에서 작성하였습니다.
- 이 문서를 다른 블로그나 홈페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.
문서정보
- 이 문서는 오라클클럽에서 작성하였습니다.
- 이 문서를 다른 블로그나 홈페이지에 게재하실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 출처 : http://www.gurubee.net/display/WEBSTUDY/Annotation?
- 오라클클럽 지식창고의 모든 문서는 크리에이티브 커먼즈의 저작자표시-비영리-동일조건변경허락(BY-NC-SA) 라이선스에 따라 자유롭게 사용할 수 있습니다.
[ 출처 : http://www.gurubee.net/display/WEBSTUDY/Annotation ]
'Java' 카테고리의 다른 글
[Java] 함께하는 개발표준 만들어 가기 (0) | 2012.04.06 |
---|---|
[Java] 한글 인코딩 테스트 (0) | 2011.12.15 |
[Java] Annotation-2 (0) | 2011.09.06 |
[Java] 자바 한글 인코딩 (0) | 2011.08.12 |
[Java] 오픈소스 정리 (0) | 2011.07.25 |