[Spring]컴포넌트 스캔과 의존관계 자동 주입 (Component Scan, Autowired)
컴포넌트 스캔이란?
- 기존에 빈을 등록할 때는 자바 설정파일이나 XML을 이용해 일일이 등록해주어야 했다.
- 실무에서는 이렇게 등록해주어야 할 빈이 수십, 수백개가 되므로 누락하거나 반복해야하는 문제점이 발생한다.
- 그렇기에 스프링은 설정정보가 없어도 자동으로 스프링 빈을 등록해주는 컴포넌트 스캔 이라는 기능을 제공한다.
@Configuration
@ComponentScan(
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
}
컴포넌트 스캔을 사용하려면 설정정보에 @ComponentScan 어노테이션을 달아준다.
기존 설정파일과 다르게 Bean으로 등록된 클래스가 하나도 없다.
중간의 excludeFilters는 스캔 대상에서 제외하는 명령어이다.
@Configuration이 붙어있는 설정정보도 자동으로 등록되기 때문에 앞서 만든 예제에서 만든 설정정보가 중복실행 되므로 excludeFilters로 설정정보는 컴포넌트 스캔 대상에서 제외했다.
ComponentScan은 @Component 어노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다. @Component를 붙여주면 된다. (Configuration 어노테이션 소스코드에도 @Component가 붙어있음)
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
@Component로 클래스를 빈 등록할 수 있지만 그 안의 의존관계는 자동으로 이루어지지 않는다.
여기서 의존관계가 필요한 부분에 @Autowired를 사용해준다.
그러면 스프링이 스프링 컨테이너 안에서 Autowired 어노테이션이 붙은 요소의 타입에 맞는 구현체를 주입해준다.
이 때 빈 이름은 CamelCase로 등록된다.
(빈 이름 : memberServiceImpl / 빈 객체 : MemberServiceImpl)
빈 이름을 직접 지정하고 싶으면 @Component("이름") 으로 직접 부여할 수 있다.
탐색 위치와 기본 스캔 대상
@ComponentScan(
basePackages = "hello.core.member",
)
basePackages 옵션을 통해 탐색위치를 지정할 수 있다.
위와 같이 설정하면 hello.core.member 패키지만 ComponentScan 대상이 된다.
- basePackages = {"hello.core", "hello.service"} 이렇게 여러 위치를 지정할 수 있다.
- 지정하지 않으면 @ComponentScan이 붙은 정보 클래스의 패키지가 시작 위치가 된다.
- basePackageClasses = AutoAppConfig.class 이와 같이 클래스로 지정할 수 있음
권장하는 사용법 : 패키지 위치를 지정하지 않고 설정 정보 클래스 위치를 프로젝트 최상단에 두는 것, 예를들어 아래와 같은 프로젝트 구조가 있다.
- com.hello
- com.hello.service
- com.hello.repository
com.hello → 여기에 설정파일을 두고 ComponentScan 어노테이션을 붙여서 basePackages는 생략한다.
(스프링 부트의 경우 @SpringBootApplication이 부트의 설정 선언 어노테이션인데, 이를 프로젝트 시작 루트 위치에 두는 것이 관례이다, 이 어노테이션 안에도 @ComponentScan이 들어있음)
컴포넌트 스캔 기본 대상
컴포넌트 스캔은 @Component 뿐만 아니라 다음과 같은 내용도 대상에 포함하며 부가기능을 지니고 있다.
- @Component : 컴포넌트 스캔에 사용
- @Controller : 스프링 MVC 컨트롤러에서 사용 (스프링 MVC 컨트롤러로 인식)
- @Service : 스프링 비즈니스 로직에 사용 (특별한 기능은 없으나 서비스 로직임을 인식할 수 있음)
- @Repository : 스프링 데이터 접근 계층에서 사용 (데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환해줌)
- @Configuration : 스프링 설정 정보에서 사용 (스프링 설정 정보로 인식, 싱글톤 유지하도록 추가 처리)