2020-3-20 스프링 어노테이션 이해하기
배경
- 최근 java, spring을 다시 학습하고 있다. 예전에 학습했을때는 그냥 주먹구구식으로 코드 동작만 시켰지 원리에 대해 어떻게 사용하는지에 대한 이해가 부족했었다. 그 이유중 하나가 바로 @Service, @Transactional 등 어노테이션에 대한 이해가 안됬기때문이다. 이 부분을 차근차근 해결하고자 한다.
문제 : @Scope가 뭐에요??
@Component
@Scope(scopeName = "jimmyScope",value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {
}
- 저 코드만 봐서는 정확하게 @Scope가 어떤 동작들이 이루어지는지 알기 어려웠다.
- @Scope가 있는데 안에있는 scopeName, value, proxyMode는 어디서 가져오며 어떤것일까? 라는 궁금증이 있어서 Scope.java파일을 들어가 봤다. 아래와 같은 코드들이 있었는데, 더 멘붕이였다.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
/**
* Alias for {@link #scopeName}.
* @see #scopeName
*/
@AliasFor("scopeName")
String value() default "";
/**
* Specifies the name of the scope to use for the annotated component/bean.
* <p>Defaults to an empty string ({@code ""}) which implies
* {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
* @since 4.2
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
* @see #value
*/
@AliasFor("value")
String scopeName() default "";
/**
* Specifies whether a component should be configured as a scoped proxy
* and if so, whether the proxy should be interface-based or subclass-based.
* <p>Defaults to {@link ScopedProxyMode#DEFAULT}, which typically indicates
* that no scoped proxy should be created unless a different default
* has been configured at the component-scan instruction level.
* <p>Analogous to {@code <aop:scoped-proxy/>} support in Spring XML.
* @see ScopedProxyMode
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
-
이 문서를 어떻게 해석을 하고 이해를 해야되는가?
- 저 인터페이스 내부에 있는 메서드들을 직관적으로 이해하기로 했다. Scope라는 인터페이스에 value(), scopeName, proxyMode()라는 메서드가 정의되어 있고 각각의 default값이 있다.
- @Scope()안에있는 프로퍼티들은 Scope 인터페이스에 정의된 메서드들을 호출하는것이고 그 메서드를 호출하기 위해서 @AliasFor(“alias”)를 @Scope(alias=”value”) 불러서 사용을 하면된다.
-
내가 궁금한것들 @AliasFor, @Documented, @Retention, @Target… 어노테이션이 끝도 없다. 결국 내가 이해해야되는것은 자바의 어노테이션을 이해해야된다.
어노테이션 이해하기
- 컴파일러에 정보를 가르쳐준다.
- 컴파일할 때, 설치할때 작업을 지정
- 실행할때 별도의 처리가 필요할때
- 어노테이션은 위의 3가지 경우에 사용한다.
- 자바언어에서 사용되는 어노테이션은 3가지(@Override, @Deprecated, @SupressWarning)이고 어노테이션을 선언하기 위한 메타 어노테이션이 4개(@Target, @Retention, @Documented, @Inherited)가 있다.
- @interface : 커스텀 어노테이션을 만들때 사용한다. 대부분의 스프링 어노테이션들이 여기에 해당한다.
@Target
- 어디에 어노테이션을 적용하면 좋을지 선언할때 사용한다.
@Target(Elementtype.METHOD)
@Target({ElementType.TYPE, ElementType.METHOD})
ELEMENTTYPE
- CONSTRUCTOR
- FIELD
- LOCAL_VARIABLE
- METHOD
- PACKAGE
- PARAMETER
- TYPE : 클래스, 인터페이스, enum 등
- 예를들어 위의 코드처럼 @Target(Elementtype.METHOD)로 선언을 하면 이 어노테이션은 메서드 위에 선언을 할 수 있는것이다. @Transactional어노테이션처럼. Elementtype.TYPE으로 선언하면 @Controller, @Service와 같이 클래스를 선언할때 쓸 수 있다.
@Retention
- 얼마나 오래 어노테이션 정보가 유지되는지 선언
@Retention(RetentionPolicy.RUNTIME)
ReteionPolicy
- RUNTIME : 실행시 JVM에서 참조가능
- SOURCE : 컴파일시 정보가 사라짐
- CLASS : 컴파일러에 의해 참조가능. JVM에서는 사라짐
@Documented, @Inherited
- @Documented는 해당정보가 Javadocs에 포함된다.
- @Inherited는 모든 자식클래스에서 부모클래스의 어노테이션을 사용가능
결론 : @Scope 이해하기
- 위의 어노테이션 메서드들을 보니 @Scope의 원리를 이해할 수 있다.
- @Scope의 @Target은 Type, METHOD로 선언되어있다. @Scope는 메서드의 위나 클래스, 인터페이스, ENUM에서 사용할 수 있다.
- @Retention의 RetentionPolicy는 Runtime으로 JVM에 의해 참조가능하다.
- @Documented는 자바 공식문서에 이 스펙이 정의되어있다.
- 각 메서드에는 @AliasFor(“aliasName”)가 선언이 되어있다. 이 내용은 @Scope(aliasName=”value”)로 사용가능하다.
느낀점
- 스프링을 학습할때마다 자바문법이나 내부적으로 정의되어있는 어노테이션들 동작원리 등에 대해서 이해하는 것이 어려웠다. 오늘 이 부분을 해결하고자 자바의 커스텀어노테이션만들기을 학습하고 스프링 내부적으로 선언되어있는 어노테이션들을 차근차근 봤다. 시간은 좀 더 걸리지만 천천히 원리를 이해하면서 학습을 하니 이해가 더 잘됬다. 앞으로 자바, 스프링의 기술문서를 보고 이해하는데 많은 도움이 될거같다.
Reference
- https://stackoverflow.com/questions/9921676/what-does-class-mean-in-java
- 자바의신 17장
- https://www.inflearn.com/course/spring-framework_core/lecture/15511 => 인프런 스프링 프레임워크 핵심 기술 참조
Written on March 20, 2020