HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
[New] 타일러팀
[New] 타일러팀
/
🧙‍♂️
이창호
/
🚍
@SpringBootApplication?
🚍

@SpringBootApplication?

Created
Apr 23, 2022 05:04 AM
Tags
springboot
Property

갑자기 왜 SpringBootApplication을 알아보는거죠?

  • 코드 리뷰를 하는 중 SpringBootApplication이 있는데, ComponentScan , PropertySource 를 사용하는 이유가 무엇인지 질문이 들어왔을 때였다.
  • 사실 난 SpringBootApplication 에 대하여 왜 이걸 쓰는지 누군가에게 설명 할 수 없단걸 깨달았고 이제 알아보려 한다.
위 코드는 SpringBootApplication에 있는 annotation들이다.
 
이제 하나 씩 알아보도록 하겠다.
 

Documented

여기에 적당한 예제 코드와 설명이 있다.
 
JavaDoc으로 문서를 만들게 될 때, 어노테이션에 관한 설명도 포함되려면 Documented 가 필요하다.
 

Inherited

여기에 적당한 예제 코드와 설명이 있다.
 
Inherited 어노테이션이 있으면 해당 어노테이션 인터페이스를 사용 할 수 있게 된다.
 

Retention

여기에 적당한 예제 코드와 설명이 있다.
 
이 어노테이션은 해당 어노테이션 인터페이스가 RetentionPolicy 에 명시한 것(SOURCE, CLASS, RUNTIME) 까지만 작동하는 것을 뜻한다.
 

Target

여기에 적당한 예제 코드와 설명이 있다.
 
해당 어노테이션에 ElementType이 명시되어 있다면 명시된 타입에만 사용 할 수 있다.
 
아래는 Target 어노테이션에 들어 갈 수 있는 enum constants 값들이다.
( 포함된 링크에도 있는 표지만 누락된 정보가 있어서 여기에 정리한다. )
Element Type
Element to be Annotated declaration
Type
Class, Interface, Enum, Record declaration
FIELD
Field declaration( includes enum constants)
METHOD
Method declaration
PARAMETER
Formal Parameter declaration
CONSTRUCTOR
Constructor declaration
LOCAL_VARIABLE
Local variable declaration
ANNOTATION_TYPE
Annotation interface declaration
PACKAGE
Package declaration
TYPE_PARAMETER
Type parameter declaration
TYPE_USE
Use of a type
MODULE
Module declaration
RECORD_COMPONENT
Record component
  • TYPE_PARAMETER가 쓰이는 곳은 class name<T1, T2, ..., Tn> 에서 T1, T2다.
  • TYPE_USE가 쓰이는 곳은 @C int f; 에서 int다.
 

ComponentScan

여기에 적당한 예제 코드와 설명이 있다.
 
  • 해당 어노테이션을 사용하면 스캔할 패키지를 명시할 수 있다.
  • Exclude Filter, Include Filter, Filter로 필터링도 가능하다.

Repeatable

여기에 참고 할 만한 자료가 있다.
 
해당 어노테이션을 사용하면 어노테이션들을 반복 적용 할 수 있게 해준다.
아래는 ComponentScan에서 사용한 예시다.
 

SpringBootConfiguration

주석에는 이렇게 설명이 달려있다.
Indicates that a class provides Spring Boot application @Configuration. Can be used as an alternative to the Spring's standard @Configuration annotation so that configuration can be found automatically (for example in tests).
간략하게 말하면 configuration 대신 알아서 bean들을 찾아 준다.
 

Configuration

주석에는 이렇게 설명이 달려있다.
Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime
해당 어노테이션을 사용하는 클래스에서 메서드에 Bean 어노테이션을 붙이면 런타임 시점에서 스프링 컨테이너에 빈을 등록해 준다.

Indexed

 
코드에 있는 주석을 읽어도 이해가 안간다.
다만, 구조상 Component 어노테이션이 해당 어노테이션을 사용한다.
  • Component를 붙은 어노테이션은 스프링 컨테이너에 빈으로 등록 된다.
 
 

AliasFor

아래는 해당 어노테이션의 주석 내용 중 일부다.
 
@AliasFor is an annotation that is used to declare aliases for annotation attributes.
 
SQL문을 작성할 때, 별칭(alias)를 사용하는 것과 똑같다.
 
주석에 있는 사용 예시는 총 4가지다.
  • 어노테이션과 함께 명시적으로 사용
  • 메타 어노테이션의 Attribute에 명시적으로 사용
  • Implicit Aliases within an Annotation
  • Transitive Implicit Aliases within an Annotation

EnableAutoConfiguration

Enable auto-configuration of the Spring Application Context, attempting to guess and configure beans that you are likely to need. Auto-configuration classes are usually applied based on your classpath and what beans you have defined.

AutoConfigurationPackage

Registers packages with AutoConfigurationPackages. When no base packages or base package classes are specified, the package of the annotated class is registered
 

Import

ndicates one or more component classes to import — typically @Configuration classes.
 
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { ... }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Documented { }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Inherited { }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value(); }
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * Returns an array of the kinds of elements an annotation interface * can be applied to. * @return an array of the kinds of elements an annotation interface * can be applied to */ ElementType[] value(); }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { ... }
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Repeatable { /** * Indicates the <em>containing annotation interface</em> for the * repeatable annotation interface. * @return the containing annotation interface */ Class<? extends Annotation> value(); }
@AliasFor("classes") Class<?>[] value() default {};
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration @Indexed public @interface SpringBootConfiguration { @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor(annotation = Component.class) String value() default ""; boolean proxyBeanMethods() default true; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Indexed { }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interface AliasFor { /** * Alias for {@link #attribute}. * <p>Intended to be used instead of {@link #attribute} when {@link #annotation} * is not declared &mdash; for example: {@code @AliasFor("value")} instead of * {@code @AliasFor(attribute = "value")}. */ @AliasFor("attribute") String value() default ""; /** * The name of the attribute that <em>this</em> attribute is an alias for. * @see #value */ @AliasFor("value") String attribute() default ""; /** * The type of annotation in which the aliased {@link #attribute} is declared. * <p>Defaults to {@link Annotation}, implying that the aliased attribute is * declared in the same annotation as <em>this</em> attribute. */ Class<? extends Annotation> annotation() default Annotation.class; }
public @interface ContextConfiguration { @AliasFor("locations") String[] value() default {}; @AliasFor("value") String[] locations() default {}; // ... }
@ContextConfiguration public @interface XmlTestConfig { @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xmlFiles(); }
@ContextConfiguration public @interface MyTestConfig { @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] value() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] groovyScripts() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xmlFiles() default {}; }
@MyTestConfig public @interface GroovyOrXmlTestConfig { @AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts") String[] groovy() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xml() default {}; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Import { Class<?>[] value(); }