스프링 빈과 설정에 대해 공부할 때는 등록한 빈이 많지 않아서 어렵지 않았지만, 이후 큰 프로젝트를 진행 할 때 스프링 빈이 수십, 수백개가 된다면 일일이 수동으로 관리하기는 어려울 것입니다.
스프링은 빈 등록을 자동으로 할 수 있게 도와주는 컴포넌트 스캔 이라는 기능이 있습니다.
컴포넌트 스캔을 사용하려면 빈으로 등록하기 원하는 클래스들에 @Component 어노테이션을 추가해주고,
설정정보 파일에 @ComponentScan 어노테이션을 추가해주면
설정파일이 위치한 패키지(hello.core)부터 하위 패키지에서 @Component 어노테이션이 붙은 클래스 모두를 스캔해서 빈으로 등록합니다.
이때 빈의 이름은 클래스 이름의 첫 글자를 소문자로 바꾼 형태로 등록되게 됩니다.
예시) MemberServiceImpl
-> memberServiceImpl
빈 이름을 직접 지정하고 싶다면
@Component("지정하고자 하는 빈 이름")
이러한 형식으로 어노테이션에 인자를 전달하면 됩니다.
💡 설정 파일의 경우 프로젝트를 열었을때 바로 볼 수 있기도 하고, 컴포넌트 스캔의 대상을 프로젝트 전체로 해주기 위해 파일의 위치를 root 폴더에 두는것이 좋습니다.
수동으로 할 때는 직접 return new (구현 객체)
과 같이 명시를 해줘서 스프링이 관리를 해주었었는데, 컴포넌트 스캔으로 빈을 등록할 때 의존성 주입은 어떻게 이루어질까??
@Autowired 어노테이션을 사용해 의존관계를 자동으로 주입 시킬 수 있습니다.
@Autowired 어노테이션을 통한 자동 의존관계 주입이 동작하는 방식은 이렇습니다.
@ComponentScan을 통해 @Component가 붙은 클래스들을 스프링 빈으로 등록합니다.
이후 생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 클래스 타입에 맞는 스프링 빈을 찾아서 주입해 줍니다.
💡 생성자가 하나인 경우 @Autowired를 생략할 수 있습니다.
컴포넌트 스캔의 기본 탐색 범위는 언급했던 것처럼 @ComponentScan 어노테이션이 달린 파일의 패키지 위치부터 그 하위 패키지를 전부 탐색합니다.
스프링은 이러한 탐색 범위도 지정 할 수 있도록 기능을 지원해줍니다.
이렇게 basePackages를 인자로 전달해 탐색을 원하는 범위를 지정할 수 있습니다. 여러개의 탐색 범위는 중괄호로 감싸 전달하여 지정할 수 있습니다.
이후 스프링 MVC 를 배울 때 여러가지 어노테이션들을 배울텐데 아래의 어노테이션들은 @Component를 포함하고 있어 자동으로 컴포넌트 스캔 대상이 되는 어노테이션들입니다.
@Controller : 스프링 MVC 컨트롤러로 인식하게 해주는 어노테이션
@Repository : 데이터 접근 계층으로 인식하고, 데이터 계층의 예외(DB마다 다른 예외가 발생할 수 있음)들을 스프링이 처리할 수 있는 추상화된 스프링 예외들로 변환해줌
@Configuration : 스프링 설정 정보로 인식하고, 스프링 빈을 싱글톤으로 유지하도록 관리해줌
@Service : 딱히 큰 역할은 없지만 개발자가 주요 로직들이 들어있는 빈이라고 인식하도록 도와줌.
컴포넌트 스캔에 인자로 includeFilters, excludeFilters를 추가하여 필터에 포함할 클래스들, 제외할 클래스들을 지정할 수도 있는데, 이는 자세히 알고싶다면 김영한님의 강의를 보도록 합시다.
자동 빈 등록 vs 자동 빈 등록
컴포넌트 스캔을 통해 스프링 빈 등록시 이름이 중복되는 빈이 있다면, 에러가 발생합니다.
ConflictingBeanDefinitionException
에러 발생
UnsatisfiedDependencyException
에러 발생
수동 빈 등록 vs 자동 빈 등록
앞으로도 계속 배우겠지만 스프링은 둘중에 우선순위를 고르라면 더 자세한, 더 노력이 들어가는? 그러한 것을 우선순위를 높게 처리합니다. 따라서 자동 등록 빈과 수동 등록 빈 중에서는 수동으로 설정해놓은(AppConfig) 빈이 우선순위를 가지고 등록됩니다.
그러나 이러한 현상은 주로 의도적으로 발생하는것이 아니기에 매우 잡기 어려운 버그가 발생할 가능성이 높습니다. 이러한 문제를 방지하기위해 스프링 부트에서는 시작할 때 수동 빈과 자동 빈이 중복되면 바로 에러를 발생시켜 개발자에게 친절하게 알려줍니다.
이러한 수동 빈과 자동 빈의 중복시 수동 빈을 허용하는 방법도 있는데 이것도 필요하면 찾아보도록 하자!