[스프링(spring)] Meta-Annotaiton(@Target, @Retention,@Component)

allnight5·2023년 1월 5일
0

스프링

목록 보기
25/62

처음에는 @EnableWebSecurity사용되는 어노테이션을 정리하려 하였으나 참조사이트1에서 meta-annotaiton라는 개념이 나와서 이걸로 정리하기로 하였다.
새로운 개념에 감사합니다.
참조사이트1
참조사이트2

meta-annotaiton ?
meta-annotation 은 다른 annation 에서도 사용되는 annotation 의 경우를 말하며 custom-annotation 을 생성할 때 주로 사용됩니다.
다른 설명으로는 애노테이션의 정의에 부여된 애노테이션이라는 의미이다.

@Component도 meto-anotation입니다

@Retention이란?

@Retetion 은 Annotation 이 실제로 적용되고 유지되는 범위를 의미합니다.
어노테이션 타입을 어디까지 보유할지를 설정하는 것이라고 하네요.

public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

역시 어노테이션답게 @Retention 어노테이션에도 자기자신이 쓰입니다. @Target도 마찬가지입니다.
디폴트값은 Class 입니다. 근데 RetentionPolicy는 무엇일까요??
RetentionPolicy의 값을 넘겨주는 것으로 어노테이션의 메모리 보유 범위가 결정됩니다.

public enum RetentionPolicy { 
    SOURCE, 
    CLASS, 
    RUNTIME
}
  • SOURCE : 어노테이션을 사실상 주석처럼 사용하는 것. 컴파일러가 컴파일할때 해당 어노테이션의 메모리를 버립니다.
  • CLASS : 컴파일러가 컴파일에서는 어노테이션의 메모리를 가져가지만 실질적으로 런타임시에는 사라지게 됩니다. 런타임시에 사라진다는 것은 리플렉션으로 선언된 어노테이션 데이터를 가져올 수 없게 됩니다. 디폴트값입니다.
  • RUNTIME : 어노테이션을 런타임시에까지 사용할 수 있습니다. JVM이 자바 바이트코드가 담긴 class 파일에서 런타임환경을 구성하고 런타임을 종료할 때까지 메모리는 살아있습니다.

@Retention(RetentionPolicy.RUNTIME)
Policy 에 관련된 Annotation 으로 컴파일 이후에도 JVM 에서 참조가 가능한 RUNTIME 으로 지정합니다.

@Retention의 종류는 다음과 같습니다.

RetentionPolicy.RUNTIME
RetentionPolicy.CLASS
RetentionPolicy.SOURCE

RetentionPolicy.RUNTIME 은 컴파일 이후에도 JVM 에 의해서 계속 참조가 가능합니다. 주로 리플렉션이나 로깅에 많이 사용됩니다.

RetentionPolicy.CLASS 은 컴파일러가 클래스를 참조할 때가지 유효합니다.

RetentionPolicy.SOURCE 은 컴파일 전까지만 유효합니다. 즉, 컴파일 이후에는 사라지게 됩니다.

CLASS는 어노테이션을 단지 바이트코드에서 확인할 수 있는 수준으로만 정의해놓을 뿐 Runtime 환경에서는 역시나 버려지는 메모리인 것입니다.

SOURCE는 .class 파일에서도 보이지 않습니다. 단지 개발자의 어떤 용도로만 사용되다가 컴파일할 때 버려지는 소스이기 때문입니다.

RetentionPolicy.CLASS, RetentionPolicy.SOURCE 이 두 옵션은 Lombok과 같이 컴파일까지만 참조가 가능한 옵션이기 때문에 일반적으로는 거의 사용하지 않습니다.

@Target이란?

은 Java compiler 가 annotation 이 어디에 적용될지 결정하기 위해 사용합니다.
@Target(ElementType.TYPE)
예를 들어 위에서 사용한 ElementType.TYPE 은 해당 Annotation 은 타입 선언 시 사용한다는 의미입니다.
종류는 아래와 같습니다.

ElementType.PACKAGE : 패키지 선언
ElementType.TYPE : 타입 선언
ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
ElementType.CONSTRUCTOR : 생성자 선언
ElementType.FIELD : 멤버 변수 선언
ElementType.LOCAL_VARIABLE : 지역 변수 선언
ElementType.METHOD : 메서드 선언
ElementType.PARAMETER : 전달인자 선언
ElementType.TYPE_PARAMETER : 전달인자 타입 선언
ElementType.TYPE_USE : 타입 선언

참조사이트 3
참조사이트 4

@Component란?

컴포넌트 ( Component )
구성요소 라는 뜻으로 컴포넌트는 독립적인 단위 모듈이다. 유저가 사용하는 시스템에 대한 조작장치를 이야기한다.
스프링이 필요 시 자동으로 생성하는 클래스 목록에 추가합니다.

@Component 란
개발자가 직접 작성한 Class 를 Bean 으로 만드는 것이다.
싱글톤 클래스 빈을 생성하는 어노테이션이다. 물론 @Scope를 통해 싱글톤이 아닌 방식으로도 생성이 가능하다.
이 어노테이션은 선언적(Declarative)인 어노테이션이다.
즉, 패키지 스캔 안에 이 어노테이션은 "이 클래스를 정의했으니 빈으로 등록하라" 는 뜻이 된다.

  • ConponentScan : Component 어노테이션이 붙은 클래스들을 검색한다.

@Bean 이란
개발자가 작성한 Method 를 통해 반환되는 객체를 Bean으로 만드는 것이다.
주로 @Configuration 어노테이션이 들어간 Spring 을 설정하는 클래스 내에 들어가는 메소드에서 선언한다.

하지만!
참조3에 잘못된 생각이라는것처럼 나도
service의 위에 @Component가있어서 개념상으로 일종의 @Component는 @Service보다 작은 단위라고 생각했었다. 그런데 @Service는 @Component의 구체적인 역할을 나타내는 세부적인 관점이었다.
@Component의 구체화된 형태로 @Repository, @Service, @Controller들이 있다.
따라서 당신의 컴포넌트 클래스들에 @Component를 붙일 수 있지만, @Repository, @Service, @Controller를 붙인다면 도구들이 클래스들을 처리하는데 더 적합하도록 할 수 있고 관점(aspects)에 더 연관성을 부여할 수 있다.
여하튼 스프링에서도 @Component보다는 @Repository, @Service, @Controller를 권장하고 있었던 것이었다.

profile
공부기록하기

0개의 댓글