스프링 핵심 원리 - 5일차 (컴포넌트 스캔)
여태까지 우리는 스프링 컨테이너에 스프링 빈을 등록할때 @Bean이나 xml(지금은 거의 안씀)을 활용해서 등록을 했는데 이번에는 자동으로 빈을 등록해주는 컴포넌트에 대해 알아본다.
hello.core 패키지에 AutoAppConfig 클래스를 만든다.
package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration // 설정정보
// 자동으로 스프링 빈 등록
@ComponentScan( // 참고로 어노테이션은 메타정보임
//지정하지 않으면 해당 클래스가 있는 패키지 부터 시작(이친구부터 하위 패키지까지)
basePackages = "hello.core.member", // 모든 클래스를 다 뒤지는건 너무 오래걸리기때문에 basePackages를 통해서 패키지 서치 시작점을 지정할 수 있음
basePackageClasses = AutoAppConfig.class, // AutoAppConfig가 있는 클래스에 패키지부터 시작
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
//Configuration 어노테이션 사용한 부분도 자동으로 빈으로 등록되기때문에 위 코드를 사용해서 기존에 만들었건거 등록 안되게끔 방지함
)
public class AutoAppConfig {
}
@ComponentScan 어노테이션은 @ComponentScan이 붙은 클래스를 스프링 빈으로 등록을 해주기에 구현 클래스에 @ComponentScan을 붙인다.
이때 궁금한점이 예전에 AppConfig에는 의존관계를 직접 적어줬는데 이렇게 컴포넌트 스캔을 이용하면 어떻게 할 수 있을까? -> @Autowired를 통해서 의존관계를 자동으로 주입할 수 있다. 의존관계 주입하는 생성자 부분에 @Autowired 어노테이션을 사용한다.

위 사진은 컴포넌트 스캔을 사용했을때 어떻게 적용이 되는지 보여주는것이다. 컴포넌트 스캔을 사용하면 @Component가 붙은 클래스를 스프링 빈에 등록을 해준다. 이때 주의할점은!! 등록할때 앞글자가 소문자로 이름을 변환해서 등록을 해준다.
( ex) MemberServiceImpl -> memberServiceImpl) 만약 이름을 직접 등록하고 싶으면 @Component("이름을 직접 등록") 해서 사용하면 된다. (보통은 그냥 붙인다.)
@Autowired를 지정하면 스프링 컨테이너가 스프링 빈을 찾아서 주입을 해준다. 그래서 파라미터가 많아도 알아서 다 자동으로 주입을 해준다.
위 코드 주석으로 적은 부분중에 basePackages 라고 적힌 부분이 주석처럼 모든 클래스와 라이브러리들을 다 찾기엔 너무 오래걸리므로 탐색할 패키지 시작을 지정해서 해당 패키지부터 시작해서 해당패키지의 하위 패키지만 탐색할 수 있게 해줌.
만약 지정하지 않게되면 @ComponentScan이 붙은 곳이 시작 위치가 됨
권장방법은 지정하지않고 설정 정보 클래스를 맨위에 둔다고한다.
참고로 컴포넌트 스캔은 다른 어노테이션도 대상에 포함된다
@Controller(스프링 MVC 컨트롤러),
@Service(스프링 비즈니스 로직), (얘는 딱히 기능이 있다기보다 핵심 비즈니스 로직이 여기에 있겠구나 라고 개발자들이 확인하는데 도움을 줌)
@Repository(스프링 데이터 접근 계층),
@Configuration(스프링 설정 정보)
-> 얘네를 까보면 @Component가 붙어있음
추가로 어노테이션에서는 상속이라는 개념이 없음 그래서 어노테이션이 붙어있는지 확인하는건 java의 기능이 아니라 스프링의 기능이다.
또 필터를 통해서 컴포넌트 스캔 대상을 지정할 수 있음
includeFilters -> 컴포넌트 스캔 대상을 지정함
excludeFilters -> 컴포넌트 대상을 지정하지 않음
마지막으로 자동 등록과 충돌에 대해서 알아보자
빈이 충돌하는 경우에는
1. 자동 빈 등록 vs 자동 빈 등록
2. 자동 빈 등록 vs 수동 빈 등록
이렇게가 존재한다.
1번같은 경우에는 ConflictingBeanDefinitionException 예외 발생한다.
2번같은 경우에는 수동 빈이 자동 빈을 오버라이딩 한다(수동 빈 우선권을 가짐)
그래서 2번같은경우 개발자에 의도와 다르게 될경우 되게 애러를 찾기 어려워짐 그렇기에 스프링에서는 스프링이 돌아갔을때 오류를 뜨게 만들었다 CoreApplication을 돌려서 오류를 확인할 수 있다.