[Spring] 컴포넌트 스캔(ComponentScan)

2022. 10. 23. 21:06

스프링 빈을 등록하기 위한 방법은 두 가지가 있다.

1. 설정 정보 클래스의 메서드 레벨에 @Bean 사용하기.
    -> 몇 개 안 되는 스프링 빈을 등록할 땐 괜찮지만, 많은 빈을 등록하게 되면 귀찮고 누락 문제가 발생할 수 있다.
2. ComponentScan 사용하기

ComponentScan

@ComponentScan 애너테이션은 @Component 애너테이션이 붙어 있는 클래스를 스캔해서 자동으로 스프링 빈으로 등록해준다.

@Configuration 애너테이션이 붙은 설정 정보도 자동으로 등록하는데, @Configuration 애너테이션에도 @Component 애너테이션이 달려있기 때문이다. 이외에도 @Controller, @Service, @Repository를 찾아서 빈으로 등록해준다. 

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

수동 빈 등록

/**
 * Bean 애너테이션을 통한 수동 등록
 */
@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {}
    
    @Bean
    public MemberRepository memberRepository() {}
    
    @Bean
    public OrderService orderService() {}
    
    @Bean
    public DiscountPolicy discountPolicy() {}
}

자동 빈 등록

/**
 * ComponentScan 애너테이션을 통한 자동 등록
 */
@Configuration
@ComponentScan
public class AutoAppConfig {
}

@Component
public class MemberServiceImpl implements MemberService {
    private final MemberRepository memberRepository;

    @Autowired
    public MemberServiceImpl(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }
    //
}

@Component
public class MemoryMemberRepository implements MemberRepository {
	//
}

@Component
public class RateDiscountPolicy implements DiscountPolicy{
	//
}

@Component
public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
	//
}

@ComponentScan을 통한 자동 빈 등록은 설정 파일에 @ComponentScan과 @Configuration 애너테이션만 붙이고 안에 @Bean 애너테이션을 하나하나 적지 않았다. 빈으로 등록할 클래스에 @Component라는 애너테이션만 붙여주면 스프링이 알아서 등록해준다.

 

이때 빈 이름은 클래스의 맨 앞 글자를  소문자로 변경해서 등록한다. (MemberServieImpl -> memberServiceImpl)

빈의 이름을 직접 지정해줄 수도 있는데, @Component("namedMemberService")와 같이 지정해주면 된다. 

 

그리고 @Bean을 사용하면 메서드에서 의존관계를 주입해줬지만 @ComponentScan을 사용해서 자동으로 등록하면 @Autowired 애너테이션으로 의존관계를 주입할 수 있다. 

 

@Autowired 애너테이션이 생성자에 지정되어 있으면 스프링 컨테이너에서 해당 타입에 맞는 빈을 주입해준다.

@Bean
public MemberService memberService() {
	return new MemberServiceImpl(memberRepository());
}

@Autowired
public MemberServiceImpl(MemberRepository memberRepository){
    this.memberRepository = memberRepository;
}

@ComponentScan의 스캔 범위

@ComponentScan의 기본적인 스캔 범위는 @ComponentScan이 달려있는 설정 파일을 기준으로 자기 자신과 하위 패키지들을 탐색한다. 

 

basePackages : basePackages는 탐색 범위를 지정해줄 때 사용한다.

@ComponentScan(
        basePackages = {"com.example.hello"}
)

@ComponentScan(
        basePackages = {"com.example.hello","com.example.service"}
)

특정 패키지를 하나만 적어도 되고 여러 시작 위치를 지정해줄 수도 있다. 

 

권장되는 방법은 설정 정보 클래스의 위치를 프로젝트 최상단에 두고 basePackages를 생략하는 것이다. 

 

참고 자료  : 김영한님 스프링 핵심 원리 - 기본편

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

BELATED ARTICLES

more