카테고리 없음

Spring - Context.xml || context:component-scan

02O2 2022. 7. 15. 21:32

component-scan 란?

개요 부분에서 간략하게 언급하였지만 component-scan이란, 우리가 스프링에서 위의 이미지와 같은 어노테이션을 클래스에 함께 선언하게 되면 스프링이 자동으로 해당 어노테이션이 붙은 클래스들을 스캔하여 bean으로서 생성해주는 것을 가능하게 해주는 설정이다. 이는 기존의 XML에 장황하게 bean을 생성하기 위한 설정을 작성하는 과정을 드라마틱하게 줄여주는 방법이라 할 수 있다. 

 

  • 빈으로 등록 될 준비를 마친 클래스들을 스캔하여, 빈으로 등록해주는 것이다.
    빈으로 등록 될 준비를 하는 것이 무엇일까?
    우리가 @Controller, @Service, @Component, @Repository 어노테이션을 붙인
    클래스들이 빈으로 등록 될 준비를 한 것이다.

component-scan은 기본적으로 @Component 어노테이션을 빈 등록 대상으로 포함한다.

그렇다면 @Controller 나 @Service는 어떻게 인식하는 걸까?
그 이유는 @Controller나 @Service가 @Component를 포함하고 있기 때문이다.

base-package

  component-scan은 context xmlns(이하 xml namespace)에 정의되어 있는 접두어를 통해 사용 가능한데, 이때 위에서 언급하였듯이 어노테이션이 붙은 클래스들을 스캔하여 bean으로 만들기 위해서 base-package="패키 지명"을 통해 스캔 범위를 정할 수 있다

 

  • context:include-filter : 단어 그대로 필터를 통해 포함시키고자 하는 대상.
  • context:exclude-filter : 단어 그대로 필터를 통해 제외시키고자 하는 대상.

  이 두 가지는 모두 type, expression 속성을 갖는데, 이때 사용되는 값들은 아래와 같다.

Filter Example Expression  Description
annotation org.example.SomeAnnotation 타겟 컴포넌트의 타입 레벨에 존재하는 어노테이션을 스캔한다.
assignable org.example.SomeClass 지정한 타입과 할당(extends/implements)할 수 있는 클래스들을 스캔한다.
aspectj org.example..*Service+ aspectj의 표현식과 매치되는 컴포넌트들을 스캔한다.
regex org\.example\.Default.* 클래스 이름이 정규 표현식과 매치되는 컴포넌트들을 스캔한다.

  위의 필터와 함께 component-scan에 사용되는 중요한 속성은 use-default-filters이다. 값은 true와 false를 가질 수 있으며 기본값은 true로 @Component, @Controller, @Repository, @Service와 같은 기본 컴포넌트를 스캔한다는 의미이다. 반대로 false는 기본 컴포넌트를 스캔하지 않는다는 것이다.

 

use-default-filters 

use-default="false"는 기본 어노테이션 @Controller, @Component등을 스캔하지 않는다는 것이다.
기본 어노테이션을 스캔하지 않는다고 설정하고, include-filter를 통해서 위와 같이 특정 어노테이션만 스캔할 수 있다.

 

Root WebApplicationContext

<!-- Root Context: defines shared resources visible to all other web components -->
<!-- dependency injection 객체등록, 이 id를  new StandardServletMultipartResolver(); 얘대신 사용  -->

- @Component 포함 

- @Controller 제외 / 왜 ? SERVICE와 DAO만 넣고싶어서 

<bean id="filterMultipartResolver" 
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
<context:component-scan base-package="kr.or.ddit" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

 

반면에, @Component를 비롯한 @Repository, @Service, @Controller는 선언하고자 하는 Java 코드에 용도에 맞게 직관적으로 선언을 하기 때문에 알아보기에도, 코드를 이해하기에도 더욱 편하다.


위의 그림을 보면 각 애노테이션의 관계를 알 수 있는데, @Component가 포괄적인 선언이라면 @Repository, @Service, @Controller는 각각의 역할에 더욱 집중된 선언이다.

 

 

Servlet WebApplicationContext

- @Controller 포함

- @ ControllerAdvice 포함 

   <!-- 모든 controller는 하위 컨테이넝네 등록이 됨 -->
   <context:component-scan base-package="kr.or.ddit" use-default-filters="false">
   	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
   </context:component-scan>