앞에서 스프링 빈을 등록할때 스프링 컨테이너를 @Configuration 과 @Bean 을 사용하는 방법과
XML 을 통해 만드는 방법으로 스프링 빈을 등록했습니다.
만약 등록해야할 스프링 빈이 많아지면 설정 정보가 커지고 누락하는 문제가 발생합니다.
그래서 자동으로 스프링 빈을 등록하는 컴포넌트 스캔을 사용해보겠습니다.
시작
컴포넌트 스캔을 사용하면 @Configuration 이 붙은 설정 정보도 등록되기 때문에
Appconfig 에 붙은 @Configuration 과 @Bean 을 지워줍니다.
package hello.core;
import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.DiscountPolicy;
import hello.core.order.FixDiscountPolicy;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import hello.core.order.RateDiscountPolicy;
public class Appconfig {
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
}
다음으로 @Configuration 이 붙은 AutoAppConfig 클래스를 하나 만듭니다.
package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AutoAppConfig {
}
컴포넌트 스캔
컴포넌트 스캔은 @Component 애노테이션이 붙은 클래스를 스프링 빈으로 등록합니다.
@Configuration 애노테이션도 @Component 애노테이션을 포함하기 때문에 스프링 빈으로 등록합니다.
다음과 같이 각각의 클래스에 @Component 를 붙여줍니다.
- MemoryMemberRepository
- RateDiscountPolicy
@Component
public class MemoryMemberRepository implements MemberRepository {
...
}
@Component
public class RateDiscountPolicy implements DiscountPolicy{
}
다음 클래스에는 @Component 와 @Autowired 를 붙여줍니다.
- MemberServicelmpl
- OrderServicelmpl
package hello.core.member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
// TODO Auto-generated constructor stub
this.memberRepository = memberRepository;
}
...
}
package hello.core.order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
// TODO Auto-generated constructor stub
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
...
}
@Autowired 애노테이션은 의존관계를 주입해줍니다.
package hello.core;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import hello.core.member.MemberService;
public class AutoAppConfigTest {
@Test
void basicScan() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
MemberService memberService = ac.getBean(MemberService.class);
System.out.println("memberSerivce = " + memberService);
System.out.println("memverService.getClass() = " + memberService.getClass());
}
}
다음으로 AutoAPpConfigTest 클래스를 만들어서 등록된 빈을 타입으로 찾아확인해보면 다음과 같이 출력됩니다.
memberSerivce = hello.core.member.MemberServiceImpl@3935e9a8
memverService.getClass() = class hello.core.member.MemberServiceImpl
동작 순서
먼저 AutoAppConfig 클래스 파일에 붙은 @ComponentScan 은 @Component 가 붙은 모든 클래스를
스프링 빈으로 등록합니다. (이때, @Configuration 도 스프링 빈으로 등록됩니다.)
- 빈 이름은 클래스 명의 앞글자만 소문자가 됩니다 (MemberServiceImpl.class → memberServicelmpl)
- 빈 이름을 직접 지정하려면 @Component("memberService2") 방법 사용
다음으로 @Autowired 가 붙은 생성자에 스프링 컨테이너가 자동으로 해당 스프링 빈을 주입합니다.
탐색 위치와 대상
탐색 위치
기본 탐색 위치는 @ComponentScan 이 붙은 설정 정보 클래스의 패키지를 대상으로 탐색합니다.
( @ComponentScan 이 붙은 AutoAppConfig 클래스의 패키지인 hello.core 스캔 )
package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AutoAppConfig {
}
프로젝트의 최상단 패키지에 @ComponentScan 이 붙은 설정 정보 클래스를 두는것을 권장
탐색 대상
컴포넌트 스캔의 탐색 대상은 다음과 같습니다.
- @Component
- @Controller : 스프링 MVC 컨트롤러로 인식
- @Service
- @Repository
- @Configuration : @Component 애노테이션을 포함하고 있음
'Spring > Spring 핵심 원리' 카테고리의 다른 글
의존관계 자동주입 (0) | 2023.01.21 |
---|---|
스프링 컨테이너와 스프링 빈 (0) | 2023.01.20 |
예제 만들기 - AppConfig 생성 (0) | 2023.01.20 |
예제 만들기 - 주문과 할인 도메인 설계 (0) | 2023.01.20 |
객체 지향과 스프링 - 좋은 객체 지향 설계의 5가지 원칙 (0) | 2023.01.16 |