CS 정리/Spring

컴포넌트 스캔

tose33 2023. 11. 17. 12:13

기존의 스프링 빈 등록 & 의존성 주입 

@ComponentScan, @Autowired 사용하지 않는 기존 방식은 아래와 같다.

@Configuration
public class AppConfig {

    @Bean
    public OrderServiceImpl orderServiceImpl() {
        return new OrderServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new JDBCMemberRepository();
    }
}

위와 같이 @Configuration 클래스에서 일일히 빈 메소드 만들어서 빈이 될 클래스에서는 의존성을 주입해줘야 했다.

public class OrderServiceImpl implements OrderService{
    private MemberRepository memberRepository;

    public OrderServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}

 

 

 

@ComponentScan, @Autowired

@ComponentScan, @Autowired 를 사용하면 이전처럼 일일히 해주지 않아도 된다.

 

  • @ComponentScan
    • @Component 가 붙은 모든 클래스를 빈으로 등록
    • 빈의 기본이름은 클래스명 사용하되 첫글자 소문자 (임의로 지정도 가능)
@Configuration
@ComponentScan
public class AutoAppConfig {
}

 

  • @Autowired
    • 생성자에 @Autowired 를 지정하면, 스프링 컨테이너가 자동으로 해당 빈 찾아 주입한다
    • 타입이 같은 빈 찾아서 주입
    • 아래와 같은 경우 스프링이 MemberRepository 빈을 찾아 주입할것이다.
@Component
public class OrderServiceImpl implements OrderService{
    private MemberRepository memberRepository;

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

 

  • @Configuration 클래스에 @ComponentScan 을 설정함으로서, 스프링이 @Component 가 붙은 모든 클래스를 빈으로 등록한다.
  • 이렇게 되면 이전처럼 @Configuration 클래스에서 @Bean 으로 빈을 등록할 필요가 없어진다.
  • 따라서 의존성 주입을 @Configuration 클래스에서 할 수 없게되는데, 빈 클래스에서 @Autowired를 생성자제 붙여주면 스프링이 자동으로 의존성 주입을 수행한다.

 

 

  • @Configuration 도 들어가보면 @Component 가 붙어있다. 즉 @Configuration 이 붙은 클래스도 스캔의 대상.
@Configuration
@ComponentScan(
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
                classes = Configuration.class))
public class AutoAppConfig {
}

 

이런식으로 excludeFilters 로 제외 가능.

 

 

@ComponentScan 탐색 위치와 기본 스캔 대상

@Configuration
@ComponentScan(basePackages = "hello.springmvc.mvc")
public class AutoAppConfig {
}

 

basePackage 옵션으로 컴포넌트 스캔 시작 위치를 지정한다.

지정한 패키지 포함 하위 패키지를 모두 탐색한다.

 

basePackageClass 로 시작할 클래스를 정할수 있다.

지정 클래스의 패키지가 시작 위치가 된다.

 

지정하지 않으면 @ComponentScan 이 붙은 설정 정보 클래스의 패키지가 시작위치가 된다.

권장방법: 패키지 위치 지정하지 않고 설정 정보 클래스 (@Configuration 클래스)의 위치를 프로젝트 최상단에 둔다.

 

@Component, @Service, @Repository, @Configuration

@Component, @Service, @Repository, @Configuration 모두 자동 컴포넌트 스캔 대상.

(해당 애노테이션 클래스 소스코드 보면 @Component 가 포함되어 있음)

 

애노테이션에는 상속관계가 없다.

따라서 위의 경우처럼 어떤 애노테이션 클래스가 특정 애노테이션을 들고 있는 것을 java가 인식할수 없고,

스프링이 해주는것.

 

  • @Controller 
    • 스프링 MVC 컨트롤러로 인식
  • @Repository
    • 스프링 데이터 접근 계층으로 인식
    • 데이터 계층의 예외를 스프링 예외로 변환해준다. 즉 데이터 계층의 예외를 추상화한다. 이렇게 하면 예를들어 db를 다른 db로 바꾸면 예외도 바꾼 db로 바뀔텐데 스프링이 추상화하므로 변경에 의해 서비스같은 계층에 영향을 주지 않도록 한다.
  • @Configuration
    • 스프링 설정 정보로 인식
    • 스프링 빈이 싱글톤을 유지하도록 추가 처리 
  • @Service
    • 사실 @Service 는 특별한 처리를 하지 않는다
    • 개발자들이 핵심 비즈니스 로직이 여기 있구나라고 인식하는데 도움이된다

 

중복 등록과 충돌

  • 자동 빈 등록 vs 자동 빈 등록
    • 컴퓨넌트 스캔에 의해 자동으로 빈 등록되는데, 이름이 같은 경우 오류 발생
    • ConflicingBeanDefinitionException
  • 수동 빈 등록 vs 자동 빈 등록
    • 이 경우 수동 빈 등록이 우선권 갖는다 (수동빈이 자동빈 오버라이딩 해버림)