@ComponentScan

Ango·2023년 6월 12일

SPRING

목록 보기
6/13

@ComponentScan
해당 어노테이션이 붙은 클래스의 하위 패키지를 모두 검사하여 @Component 가 붙은 클래스들을 스프링 빈으로 등록한다.
(% 검사 대상에는 우리가 @Controller, @Service, @Repoistory 같은 어노테이션들도 해당된다 )

public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;

    
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }//생성자 주입
}    


public class OrderServiceImpl implements  OrderService{

    private final MemberRepository memberRepository ;
    private final DiscountPolicy discountPolicy;

    
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }// 생성자 주입
}

기존에는 MemberServiceImpl, OrderServiceImpl클래스에서 MemberRepository의 어떤 구현체에 의존할지를 판단하기 위해 AppConfig 파일로 가서 다음과 같이 의존성을 주입했다.

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService(){
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService(){
        System.out.println("AppConfig.orderService");

        return new OrderServiceImpl(memberRepository(),discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {

        System.out.println("AppConfig.memberRepository");
        return new MemoryMemberRepository();
    }

    @Bean
    public DiscountPolicy discountPolicy(){
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }

}

하지만이렇게 등록해야 할 스프링 빈이 수십, 수백개가 되면 일일이 등록하기도
귀찮고, 설정 정보도 커지고, 누락하는 문제도 발생한다 그래서 사용하는것이 ComponentScan 어노테이션이다.
말그대로 @Component를 Scan 해주는 기능인데 @Component붙어있는 클래스들을 자동적으로
Spring Bean에 등록해준다.

@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 OrderServiceImpl implements  OrderService{

    private final MemberRepository memberRepository ;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }// 생성자 주입
}    
    

@Autowired를 사용한 이유는 의존성 주입을 받기 위함인데 "타입" 기반으로 자동으로 의존관계를 주입해준다.

사용할 구현체에도 @Component를 달아준다.

@Component
public class RateDiscountPolicy implements DiscountPolicy {
    private int discountPercent = 10; // 10% 할인

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP){
            return price * discountPercent / 100;
        }else{
            return 0;
        }
    }
}
@Component
public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();
    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }

}

나는 spring boot를 사용하여 개발을 했을땐 분명 @ComponentScan을 사용한적이 없었다.
그 이유는 @ComponentScan이 해당 어노테이션이 붙은 클래스의 하위부를 모두 검사해주기 때문인데 Springboot의 메인 어플리케이션에는

@SpringBootApplication
public class CoreApplication {

	public static void main(String[] args) {
		SpringApplication.run(CoreApplication.class, args);
	}

}

위와 같이 @SpringBootApplication이 달려있다. 안으로 들어가보면
사진과 같이 @ComponentScan 어노테이션을 포함하고 있었다.
메인 어플리케이션은 항상 프로젝트 최상단에 있었으니 @ComponentScan을 사용할 필요가 없었던것이다.
이렇게 멋모르고 사용했던 Spring boot의 장점을 하나 알아간다..

profile
웹 벡엔드 개발자가 되어보자!

0개의 댓글