티스토리 뷰

stereotype annotation들을 어떻게 찾을까?

스프링 부트가 시작되는 클래스에 붙어있는 SpringBootApplication 어노테이션을 조사해보았습니다.

여러 어노테이션이 있으나 @EnableAutoConfiguration와 @ComponentScan을 살펴보겠습니다.

1. EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

  /**
   * Environment property that can be used to override when auto-configuration is
   * enabled.
   */
  String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

  /**
   * Exclude specific auto-configuration classes such that they will never be applied.
   * @return the classes to exclude
   */
  Class<?>[] exclude() default {};

  /**
   * Exclude specific auto-configuration class names such that they will never be
   * applied.
   * @return the class names to exclude
   * @since 1.3.0
   */
  String[] excludeName() default {};

}

스프링 애플리케이션 컨텍스트의 auto-configuration을 사용하도록 설정하여 필요할 것 같은 bean을 추측하고 구성합니다.

auto-configuration 클래스는 일반적으로 classpath와 정의한 bean을 기준으로 적용됩니다.

예를 들어, classpath에 tomcat-embedded.jar가 있는 경우, TomcatServletWebServerFactory을 원할 수 있습니다. (자신의 ServletWebServerFactory bean을 정의하지 않았음에도)

@SpringBootApplication을 사용할 때 컨텍스트의 auto-configuration이 자동으로 활성화되므로 이 주석을 추가해도 아무런 효과가 없습니다.

auto-configuration은 가능한 한 지능적이게 노력하며 사용자 자신의 configuration을 더 많이 정의할수록 후순위로 밀려납니다.

적용하지 않을 구성은 exclude()로 제외할 수 있습니다.

또한 spring.autoconfigure.exclude property를 통해 제외할 수 있습니다.

auto-configuration는 항상 사용자 정의 bean을 등록한 후에 적용됩니다.

일반적으로 @SpringBootApplication을 통해 @EnableAutoConfiguration이 선언된 클래스의 패키지는 특정 의미를 가지며 종종 '기본값'으로 사용됩니다.

예를 들어 @Entity 클래스를 검색할 때 사용됩니다.

일반적으로 모든 하위 패키지 및 클래스를 검색할 수 있도록 루트 패키지에 @EnableAutoConfiguration(@SpringBootApplication을 사용하지 않는 경우)를 배치하는 것이 좋습니다.

auto-configuration 클래스는 일반적으로 Spring의 @Configuration bean입니다.

ImportCandidates 및 SpringFactoriesLoader 메커니즘을 사용하여 위치를 파악합니다.

SpringFactoriesLoader는 META-INF/spring.factories 파일을 사용합니다.

일반적으로 auto-configuration 빈은 @Conditional이 붙은 Bean입니다.

(대부분 @ConditionalOnClass 및 @ConditionalOnMissingBean 주석을 사용합니다).

2. ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

  @AliasFor("basePackages")
  String[] value() default {};

  @AliasFor("value")
  String[] basePackages() default {};

  Class<?>[] basePackageClasses() default {};

  Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

  Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

  ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

  String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

  boolean useDefaultFilters() default true;

  Filter[] includeFilters() default {};

  Filter[] excludeFilters() default {};

  boolean lazyInit() default false;

  @Retention(RetentionPolicy.RUNTIME)
  @Target({})
  @interface Filter {

    FilterType type() default FilterType.ANNOTATION;

    @AliasFor("classes")
    Class<?>[] value() default {};

    @AliasFor("value")
    Class<?>[] classes() default {};

    String[] pattern() default {};
  }
}

@Configuration을 사용하는 클래스에서 사용할 component scanning 지시문을 구성합니다.

Spring XML의 <context:component-scan> 요소를 병렬로 지원합니다.

검색할 특정 패키지를 정의하기 위해 basePackageClasses() 또는 basePackages() 또는 해당 별칭 값()을 지정할 수 있습니다.

특정 패키지가 정의되지 않은 경우 ComponentScan 어노테이션을 선언하는 클래스의 패키지에서 검색이 수행됩니다.

<context:component-scan> 요소에는 annotation-config 속성이 있지만, ComponentScan 주석에는 없습니다.

이는 @ComponentScan을 사용할 때 거의 모든 경우에 기본 주석 구성 처리(예: @Autowired)가 가정되기 때문입니다.

또한 AnnotationConfigApplicationContext를 사용할 때 annotation config 프로세서는 항상 등록되므로 @ComponentScan 수준에서 사용하지 않도록 설정하려는 시도는 무시됩니다.

@Configuration을 사용하는 클래스를 스캔한다고 하니 @Configuration도 살펴보겠습니다.

3. Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

  @AliasFor(annotation = Component.class)
  String value() default "";

  boolean proxyBeanMethods() default true;

}

클래스가 하나 이상의 @Bean 메서드를 선언하고 런타임에 해당 bean에 대한 bean 정의 및 서비스 요청을 생성하기 위해 스프링 컨테이너에 의해 처리될 수 있음을 나타냅니다.

@Configuration
 public class AppConfig {

     @Bean
     public MyBean myBean() {
         // instantiate, configure and return bean ...
     }
 }

@Configuration 클래스는 일반적으로 AnnotationConfigApplicationContext 혹은 AnnotationConfigWebApplicationContext를 사용하여 부트스트랩됩니다.

AnnotationConfigApplicationContext의 간단한 예는 다음과 같습니다.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
 ctx.register(AppConfig.class);
 ctx.refresh();
 MyBean myBean = ctx.getBean(MyBean.class);
 // use myBean ...

AnnotationConfigApplicationContext에 직접 @Configuration 클래스를 등록하는 대신 @Configuration 클래스를 Spring XML 파일 내에서 일반 <bean> 정의로 선언할 수 있습니다.

<beans>
    <context:annotation-config/>
    <bean class="com.acme.AppConfig"/>
 </beans>

위의 예에서 ConfigurationClassPostProcessor 및 @Configuration 클래스를 쉽게 처리할 수 있는 다른 주석 관련 포스트 프로세서를 활성화하려면 <context:annotation-config/>가 필요합니다.

@Configuration은 @Component에 meta-annotated되므로 @Configuration 클래스는 component scanning의 후보입니다.

따라서 일반 @Component처럼 @Autowired/@Inject를 활용할 수도 있습니다.

특히, 단일 생성자가 존재하는 경우 자동으로 해당 생성자에 대해 적용될 것입니다.

@Configuration
 public class AppConfig {

     private final SomeBean someBean;

     public AppConfig(SomeBean someBean) {
         this.someBean = someBean;
     }

     // @Bean definition using "SomeBean"

 }

@Configuration 클래스는 component scanning을 사용하여 부트스트랩할 수 있을 뿐만 아니라 @ComponentScan 주석을 사용하여 구성 요소 검색을 구성할 수도 있습니다.

@Configuration
 @ComponentScan("com.acme.app.services")
 public class AppConfig {
     // various @Bean definitions ...
 }

결론

@SpringBootApplication에 있는 @ComponentScan에서 @Configuration을 사용하는 클래스에서 사용할 component scanning 지시문을 구성합니다.

@Configuration은 @Component에 meta-annotated되므로 @Component 클래스 또한 component scanning의 후보입니다.

전 포스팅에서 살펴봤듯이 Indexed 제외한 stereotype 어노테이션이 붙은 어노테이션들은 @Component가 붙어있습니다.

 

stereotype annotation?

stereotype annotation이 무엇일까? 전체 아키텍처에서 type 혹은 method의 역할을 나타내는 어노테이션을 뜻합니다. 종류로는 Component, Controller, Indexed, Repository, Service가 있습니다. 1. Indexed @Tar..

kkoon9.tistory.com

따라서, stereotype 어노테이션이 bean으로 등록될 수 있었던 겁니다.

'Sping Framework' 카테고리의 다른 글

스프링의 IoC  (0) 2022.07.10
자바빈(JavaBean)  (0) 2022.07.10
stereotype annotation?  (0) 2022.06.21
Spring MVC lifecycle  (0) 2022.05.15
XML In Java [2]. XML String to VO  (0) 2022.04.23
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함