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 자동 빈 등록
- 이 경우 수동 빈 등록이 우선권 갖는다 (수동빈이 자동빈 오버라이딩 해버림)