-
[Spring] 컴포넌트 스캔과 의존관계 자동 주입Backend Dev/Spring Framework 2022. 3. 15. 17:00728x90
컴포넌트 스캔
스프링 빈 등록 시 @Bean 또는 XML의 <bean>을 통해 설정 정보에 등록할 스프링 빈을 직접 나열하고, 의존 관계도 직접 명시했으나 등록해야 할 빈이 많아진다면 등록하는데 시간도 들뿐더러 실수의 가능성이 높아질 것이다.
스프링에서는 수동 구성(설정) 정보가 없어도 자동으로 스프링 빈을 등록해주는 @ComponentScan과 의존 관계도 자동으로 주입해주는 @Autowired 기능을 제공한다.@Configuration @ComponentScan( excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class)) public class AutoAppConfig { }
@ComponentScan 을 구성 정보에 붙여주어 컴포넌트 스캔을 사용할 수 있다. 컴포넌트 스캔 사용시 @Configuration이 붙은 설정 정보 또한 컴포넌트로써 빈 등록되므로 동일 패키지 내 기타 설정 정보도 함께 등록되고 실행된다. 따라서, excludeFilters를 이용해서 필요없는 설정 정보를 컴포넌트 스캔 대상에서 제외시켰다.
참고로, includeFilters는 컴포넌트 스캔 대상을 추가로 지정해주지만 @Component로 구분하기에 주로 사용되지는 않고 excludeFilters의 경우 컴포넌트 스캔에서 제외할 대상 지정해주는 필터이다. 필터 타입은 애노테이션이 기본 값이다.
@Component : 빈으로 자동 등록하고자 하는 클래스에 붙는 애노테이션 (컴포넌트 스캔의 대상)@Autowired : 의존 관계 자동 주입을 위한 애노테이션
@Component public class MemberServiceImpl implements MemberService { private final MemberRepository memberRepository; @Autowired public MemberServiceImpl(MemberRepository memberRepository) { this.memberRepository = memberRepository; } }
@ComponentScan 컴포넌트 스캔
@Component가 붙은 모든 클래스를 스프링 빈으로 등록하고, 이때 스프링 빈의 기본명은 클래스명을 사용하지만 맨 앞글자만 소문자로 바뀌어 등록된다. 직접 지정하고 싶은 경우 애노테이션 옆에 ("이름") 을 부여한다.
@Autowired 의존관계 주입
생성자에 @Autowired를 지정하면 스프링 컨테이너가 자동으로 스프링 빈을 찾아 주입힌다. 기본 조회는 타입이 같은 빈을 찾아서 "getBean(MemberRepository.class)"와 같이 조회한다.생성자에 파라미터가 2개 이상인 경우에도 자동으로 스프링 컨테이너에서 찾아 주입해준다.
탐색 위치와 기본 스캔 대상
모든 자바 클래스를 컴포넌트 스캔할 시 시간이 오래걸리므로 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다. 지정하지 않을시 디폴트는 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.
basePackages : 탐색할 패키지의 시작 위치를 지정해 해당 패키지를 포함해서 하위 패키지를 모두 탐색
basePackageClasses : 지정한 클래스의 패키지를 탐색 시작 위치로 지정
패키지 위치를 지정하지않고 설정 정보 클래스의 위치를 프로젝트 최상단에 두는 게 좋으며 스프링 부트 컴포넌트 스캔의 방법도 이와 같다. 스프링 부트 사용할 때도 메인 설정 정보이자 @ComponentScan이 포함된 @SpringBootApplication 을 프로젝트 시작 위치에 두어야 한다.
컴포넌트 스캔 기본 대상
@Component뿐만 아니라 아래의 애노테이션도 스캔 대상에 포함되고 스프링 부가기능을 수행한다. 애노테이션 간 상속관계는 없으므로 애노테이션이 특정 애노테이션을 갖고 있는 걸 인식하는 것은 스프링이 지원하는 기능이다.@Controller : 스프링 MVC 컨트롤러에 사용
@Repository : 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환
@Configuration : 스프링 설정정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가처리(CGLIB)
@Service : 개발자들이 핵심 비즈니스 로직은 해당 클래스에 있을 것이라고 비즈니스 계층을 인식하는데 도움중복 등록에 의해 충돌이 일어난다면...?
컴포넌트 스캔에서 같은 빈 이름이 등록되는 경우는 다음과 같다.
- 자동 빈 등록 vs 자동 빈 등록
컴포넌트 스캔에 의해 자동으로 스프링 빈이 등록되는 도중 이름이 같은 경우 예외(ConflictingBeanDefinitionException)를 발생시킨다
- 수동 빈 등록 vs 자동 빈 등록
수동으로 빈을 등록할 때 이름과 자동으로 등록된 빈의 이름이 충돌하는 경우 수동 빈이 자동 빈을 오버라이딩하여 우선적으로 동작한다.@Component public class MemoryMemberRepository implements MemberRepository { } @Configuration @ComponentScan public class AutoAppConfig { @Bean(name = "memoryMemberRepository") public MemberRepository memberRepository() { return new MemoryMemberRepository(); } }
의도한 경우보다는 복잡한 설정에 의해 이러한 결과가 발생하는 경우가 대부분이므로 스프링 부트에서는 수동 빈과 자동 빈이 충돌나면 오류가 발생하도록 한다. 이는 application.properties에 setting값을 주어 오버라이딩 되게끔 설정이 가능하다.
본 내용은 인프런 핵심원리 - 기본편 김영한님의 강의를 참고하였습니다.
728x90'Backend Dev > Spring Framework' 카테고리의 다른 글
[Spring] 동일 타입 빈 조회 (0) 2022.03.16 [Spring] 의존 관계 주입의 다양한 방식 (0) 2022.03.16 [Spring] 싱글톤 컨테이너 (0) 2022.03.08 [Spring] IoC, DI 그리고 컨테이너 (0) 2022.03.08 [Spring] 객체 지향 설계의 적용 (0) 2022.03.08