Java

자바 어노테이션의 모든것 - (1)

[하마] 이승현 (wowlsh93@gmail.com) 2015. 7. 4. 09:21


선선한 토요일 아침에 뭐 할까 하다가 , 자바 어노테이션에 대해서 간략하게 정리해 놓아야겠다고 생각하고 

참고 싸이트들을 검색해보니, 오래된 기술이다 보니 역시나 좋은 글들이 많아서 .그것들을 번역/정리해 

보다보니 생각한것보다 엄청 길어져버렸다. ㅜㅜ




순서

1. 자바 어노테이션 기본 문법

2. 자바 어노테이션 이야기 

3. 자바 리플렉션으로 어노테이션 다루기 

4. 스프링 설정  어노테이션 vs XML





1. 자바 어노테이션 기본 문법


Annotation 이름 

기본적으로 요렇게 생김

@Entity

@ <-- 요놈은 기본적으로 컴파일러에게 이게 어노테이션이다라고 알린다. 

@ 마크 다음에 오는 문자는  해당 어노테이션의 이름이고 여기서는  "Entity" !!!


Annotation 요소 (Element)

자바 어노테이션은 값을 세팅할수있는 요소들을 가질수있는데  속성이나 파라미터 쯤이라고 볼수있지.
@Entity(tableName = "vehicles")

위에서는 tableName 이라는 이름의 요소를 하나 가지고있다는뜻이야. 값은 "vehicles" 이군. 

물론 아래와 같이 여러개의 요소를 가질수도있어.

@Entity(tableName = "vehicles", primaryKey = "id")

하나만 요소로 가질 경우 다음과 같이 짧게 줄여 쓸수도있지.

@InsertNew("yes")


Annotation 선언위치(Placement)

어노테이션은 클래스, 인터페이스, 메소드, 메소드 파라미터, 필드, 지역변수 위에 위치할수있어.

아래는 클래스 위에 선언되어있는 것이고

@Entity
public class Vehicle {
}

위에 말했다시피 @로 시작하고 이름은 Entity 야.  Entity 어노테이션은 그냥 내가 만든 어노테이션이고 현재 별 의미 없어. :-) 


아래 예는  모든 선언 위치에 어노테이션(주석)을 넣어봤어 함 봐바~  

(뭐 큰 역할을 하는건 아니지만 우리가 항상 사용하는 //  요런  주석으로써의 의미는 있다고 볼수있지  ) 

@Entity
public class Vehicle {

    @Persistent
    protected String vehicleName = null;


    @Getter
    public String getVehicleName() {
        return this.vehicleName;
    }

    public void setVehicleName(@Optional vehicleName) {
        this.vehicleName = vehicleName;
    }

    public List addVehicleNameToList(List names) {

        @Optional
        List localNames = names;

        if(localNames == null) {
            localNames = new ArrayList();
        }
        localNames.add(getVehicleName());

        return localNames;
    }

}


자바에서 기본적으로 제공되는 어노테이션 

  • @Deprecated
  • @Override
  • @SuppressWarnings

@Deprecated

이 어노테이션은 , 해당 클래스/메소드 등은 더이상 지원하지 않으니 or  만들고 나니깐 별로 안좋은 

부분이 많거나, 더 좋은 해결법이 생겼으니 사용하지 마시라는 의미야. 그럼에도 불구하고 네가 그걸 

쓴다면 자바 컴파일러는 귀신같이 알아내서 경고 메세지를 날려줄것이지. 

(@Deprecated 주석때문에 컴파일러가 알아차릴수있는거라는 말

@Deprecated
public class MyComponent {

}

@Override

이 어노테이션은 슈퍼클래스에 대해 오버라이드 되었다는걸 알려줘. 따라서 만약 메서드가 

슈퍼클래스와 매칭되지 않았으면 에러를 날려주지. (컴파일러 만드는 사람들이 에러를 감지하기 

편하겠지?)  아래 예를 봅시다~

public class MySuperClass {

    public void doTheThing() {
        System.out.println("Do the thing");
    }
}


public class MySubClass extends MySuperClass{

    @Override
    public void doTheThing() {
        System.out.println("Do it differently");
    }
}

물론 이 어노테이션을 사용하는게 강제는 아니지만 , 사용하는게 좋을꺼야. 만약 슈퍼클래스가 

변경
되었는데 그걸 모르고 자식클래스에서 오버라이딩한 클래스를 그대로 냅두면, 의도가 

깨져버리고 
우리는 그 사실도 모른채 퇴근을 하겠지~  만약 @Override 를 선언해뒀다면 

바로 에러로 알려주고 네
가 수정한후에 편한마음으로 컴백홈하게 도와줄꺼야

@SuppressWarnings 

이 어노테이션은 해당 메소드에 대해서 compiler suppress warnings (컴파일러 경고 억제?)을 

만들어. 예를들어 어떤 코드가 경고메세지를 수천개씩 쏟아내는데, 그게 보기싫을때 입막음 

시켜버리는거야 조용히~

@SuppressWarnings
public void methodWithWarning() {


}


개인용 어노테이션 만들기 


개인적으로 사용할 어노테이션을 만드는것이  가능하며 어노테이션은 클래스나 인터페이스처럼 

자신의 파일에 정의된다. 다음 예를 보자.

@interface MyAnnotation { String value(); String name(); int age(); String[] newNames(); }

위의 어노테이션은 4개의 요소를 가지고있고 이름은 MyAnnotation  이다.

@interface 키워드를 주목하라  이것은 자바컴파일러에게 이놈이 어노테이션 정의라는걸 알려준다.

요소들은 인터페이스에서의 메서드 정의와 유사하다.  자바 기본요소들을 모두 사용할수있고 , 배열도 사용가능하다. (복잡객체사용은 불가능) 


 위에서 정의한 어노테이션을 사용해 보자.

@MyAnnotation(
    value="123",
    name="Jakob",
    age=37,
    newNames={"Jenkov", "Peterson"}
)
public class MyClass {


}

위에 보다시피 각각의 요소에 나만의 값을 지정했다. 후에 프레임워크에서  이 값을 파싱해서 필요한 정보를 알아낼것이다. 물론 님 스스로  리플렉션을 통해 저 어노테이션을 분석해서 사용할수도 있을테고~

* 저런 주석을 달아놓으면 나중에 클래스별로 그루핑을 할때 사용하거나 어떤 클래스/함수는 어떤것(URL 따위들) 과 매핑 같은것에 사용할수 있을거라는 생각을 잠시 해보자. 함수이름이 달라져도 어노테이션만 같으면 자동 매핑해줄수있지 않겠는가 


요소(Element)디폴트 값

요소에 기본값을 설정할수 있다. 아래 예를 보자.

@interface MyAnnotation {

    String   value() default "";

    String   name();
    int      age();
    String[] newNames();

}

디폴트값을 설정해두면 아래와 같이 사용할때 값을 넣지 않아도 된다. (아예 보이지도 않음) 

@MyAnnotation(
    name="Jakob",
    age=37,
    newNames={"Jenkov", "Peterson"}
)
public class MyClass {


}


@Retention    -  네이버 사전 :  (어떤 것을 잃지 않는) 보유[유지])

얼마나 오랫동안 어노테이션 정보가 유지되는지 설정할수있다. 


SOURCE    : 어노테이션 정보가 컴파일시 사라짐, 바이트코드에서는 존재하지 않음.

                  (example: @Override, @SuppressWarnings)

CLASS      :  클래스 파일에 존재하고 컴파일러에 의해 사용가능, 가상머신(런타임)에서는 사라짐.

RUNTIME  :  실행시 어노테이션 정보가 가상 머신에 의해서 참조 가능. 자바리플렉션에 의해 사용


아래 예를 보자. 

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation {

    String   value() default "";

}


@Target 

자신이 만든 어노테이션이 사용되게될 자바 요소를 지정할수있다. 아래 예를 보자.

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
public @interface MyAnnotation {

    String   value();
}

위처럼 만들면 메소드에서만 사용가능한 어노테이션을 정의할수있다.아래와 같이 타겟을 정할수있다.

  • ElementType.ANNOTATION_TYPE
  • ElementType.CONSTRUCTOR
  • ElementType.FIELD
  • ElementType.LOCAL_VARIABLE
  • ElementType.METHOD
  • ElementType.PACKAGE
  • ElementType.PARAMETER
  • ElementType.TYPE

@Inherited

The @Inherited 어노테이션은 이 어노테이션을 사용한 슈퍼클래스를 상속한 서브클래스에서도
해당 어노테이션을 갖도록 한다.

java.lang.annotation.Inherited

@Inherited
public @interface MyAnnotation {

}
@MyAnnotation
public class MySuperClass { ... }
public class MySubClass extends MySuperClass { ... }

MySubClass 클래스는 @MyAnnotation 을 상속한다. 


@Documented

@Documented 어노테이션이 지정된 대상의 JavaDoc 에 이 어노테이션의 존재를 표기하도록 지정.

java.lang.annotation.Documented

@Documented
public @interface MyAnnotation {

}
@MyAnnotation
public class MySuperClass { ... }






Reference 

http://tutorials.jenkov.com/java-reflection/annotations.html

http://tutorials.jenkov.com/java/annotations.html

http://www.javacodegeeks.com/2014/11/java-annotations-tutorial.html

http://hmkcode.com/spring-configuration-xml-annotation-java/