본문 바로가기

백엔드 잡학사전

[스프링 핵심] 컴포넌트 스캔 & 의존관계 자동 주입

스프링 빈을 하나하나 @Bean으로 만들어주지 않아도 되는 방법이 있다. 그 기능의 이름은 컴포넌트 스캔.

 

컴포넌트 스캔

@ComponentScan 애노테이션은 @가 붙은 모두 빈들을 자동 등록한다.

만약 등록을 빼고 싶은 애가 있다면 예외등록도 가능하다 - excludeFilters.

package hello.core;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
@ComponentScan(
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
}

 

그러고 필요한 곳들에 @Component 와 @Autowired를 붙여주고, 이를 테스트해주기 위해서 테스트코드를 작성해줬다.

 

package hello.core.scan;

import hello.core.member.MemberService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AutoAppConfigTest {

    @Test
    void basicScan(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);

        MemberService memberService = ac.getBean(MemberService.class);
        Assertions.assertThat(memberService).isInstanceOf(MemberService.class);
    }
}

 

이렇게 해주면 문제없이 해결이 된다.

 

이 기저의 원리는 다음과 같다.

 

또한, @ComponentScan 시에 basePackages로 탐색 패키지를 지정할 수 있다. 여러개도 가능하다.

만약 지정하지 않으면, @ComponentScan가 위치한 패키지 포함 하위를 모두 탐색한다.

 

참고로 Spring boot를 쓰면, 이미 가장 최상단인 @SpringBootApplication에 @ComponentScan이 있기 때문에 디폴트는 거기다. 그리고 @ComponentScan의 경우, @Component, @Controller, @Service, @Repository, @Configuration 모두 스캐닝에 포함한다. 그 이유는 다음과 같다.

 

필터링

또한 필터링도 가능한데, 예를 들면 

 

 

=> 이런 게 있다는 것만 확인하고, 나중에 디테일을 다시 체크하도록 하자.

 

등록끼리의 충돌

자동 빈 등록 vs 자동 빈 등록: 충돌 일어난다: ConflictingBeanDefinitionException

자동 빈 등록 vs 수동 빈 등록: 수동이 우선권을 가져가서, 오버라이딩 해버린다.

                                                스프링 부트 에러가 뜨지만, overriding=true로 시전해주면 된다.