스프링 component-scan의 개념과 동작 과정에 대해 알아보려고 한다!
얼마 전 면접에서 component-scan의 동작 과정에 대해 설명해달라는 질문을 받았다...
질문을 받았을 때, component-scan...? 이것은..스캔하는건데...뭐라 설명을 못했다..
집에 돌아오는 길에 생각해보니 부끄럽지만 내 자신이 정확한 개념도 모르고 있는 것 같았다.
이를 통해 component-scan에 대해 공부하고 정리해보았다.
@Controller
, @Service
, @Component
, @Repository
어노테이션을 붙인component-scan은 기본적으로 @Component 어노테이션을
빈 등록 대상으로 포함한다.
그렇다면 @Controller 나 @Service는 어떻게 인식하는 걸까?
그 이유는 @Controller나 @Service가 @Component를 포함하고 있기 때문이다.
component-scan 을 사용하는 방법은
xml 파일에 설정하는 방법
, 과 자바파일안에서 설정하는 방법
이 있다.
1. xml 파일에 설정
<context:component-scan base-package="com.rcod.lifelog"/>
다음과 같이 xml 파일에 설정하고, base package를 적어주면
base package 기준으로 클래스들을 스캔하여 빈으로 등록한다.
base package에 여러개의 패키지를 쓸 수 있다.
<context:component-scan base-package="com.rcod.lifelog, com.rcod.example"/>
위와 같이 설정하면, base pacakage 하위의 @Controller, @Service
@Repository, @Component 클래스가 모두 빈으로 등록되므로,
특정한 객체만 빈으로 등록하여 사용하고 싶다면
include-filter
나 exclude-filter
를 통해 설정할 수 있다.
<context:component-scan base-package="com.rcod.lifelog">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
@Controller 를 제외하고 싶다면 위와 같이 exclude-filter
를 사용하여
org.springframework.stereotype.Controller
를 명시해준다.
<context:component-scan base-package="com.rcod.lifelog" use-default="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
use-default="false"
는 기본 어노테이션 @Controller, @Component등을
스캔하지 않는다는 것이다.
기본 어노테이션을 스캔하지 않는다고 설정하고, include-filter
를 통해서
위와 같이 특정 어노테이션만 스캔할 수 있다.
2. 자바 파일안에서 설정
@Configuration
@ComponentScan(basePackages = "com.rcod.lifelog")
public class ApplicationConfig {
}
@Configuration
은 이 클래스가 xml을 대체하는 설정 파일임을 알려준다.
해당 클래스를 설정 파일로 설정하고 @ComponentScan
을 통하여
basePackages
를 설정해준다.
component-scan
을 사용하는 두 가지 방법이 있다. <bean id="mssqlDAO" class="com.test.spr.MssqlDAO"></bean>
<!-- MemberList 객체에 대한 정보 전달 및 의존성 주입 -->
<bean id="member" class="com.test.spr.MemberList">
<!-- 속성의 이름을 지정하여 주입 -->
<property name="dao">
<ref bean="mssqlDAO"/>
</property>
</bean>
MssqlDAO
와 MemberList
를 빈으로 등록하고,
MemberList에 Mssql을 주입한 것이다.
위와 같이 코드가 매우 길어지고, 일일이 추가하기에 복잡해진다.
ConfigurationClassParser 가 Configuration 클래스를 파싱한다.
@Configuration 어노테이션 클래스를 파싱하는 것이다.
⬇
ComponentScan 설정을 파싱한다.
base-package 에 설정한 패키지를 기준으로
ComponentScanAnnotationParser가 스캔하기 위한 설정을 파싱한다.
⬇
base-package 설정을 바탕으로 모든 클래스를 로딩한다.
⬇
ClassLoader가 로딩한 클래스들을 BeanDefinition으로 정의한다.
생성할 빈의 대한 정의를 하는 것이다.
⬇
생성할 빈에 대한 정의를 토대로 빈을 생성한다.
동작 과정은 References 의 마지막 두 개의 블로그를 참고했습니다.
잘못된 부분이 있다면 언제든지 댓글로 알려주세요😄
https://yookeun.github.io/java/2014/07/04/spring-component-scan/
https://zorba91.tistory.com/249
https://galid1.tistory.com/494
https://jess-m.tistory.com/14
https://yonggar-ri.tistory.com/entry/Spring-ComponentScan-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EB%B6%84%EC%84%9D
완전 이해 쏙쏙이었습니다. 감사합니다. d