이 시리즈는 인프런 강의(김영한 님의 ‘스프링 핵심 원리 - 기본편’)로 공부하며 혼자 기록하고, 사람들과도 공유할 수 있도록 작성하는 글이다. 최대한 추가적인 정보는 공식 홈페이지, 문서를 보며 얻을 예정이다.
(개인적인 생각과 이해가 들어가 있기 때문에 저의 ‘무식함’이 있을 수 있습니다😜 혹시라도 이 글을 보게 되시는 분이 계시다면 잘못된 부분 댓글로 많이 알려주시면 너무 감사하겠습니다!!)
GitHub Repository : https://github.com/jcw1031/spring-core-study
@Autowired
는 기본이 타입으로 조회한다. 타입으로 조회하는 경우 선택된 빈이 2개 이상일 때 문제가 발생한다. DiscountPolicy
의 구현체인 RateDiscountPolicy
와 FixDiscountPolicy
둘 다 스프링 빈으로 선언되었을 때 오류가 발생한다.
RateDiscountPolicy
와 FixDiscoutPolicy
에 모두 @Component
를 붙인 후, AutoAppConfigTest
클래스의 basicScan()
테스트를 실행하면 오류가 발생한다. 하나의 매칭을 기대했지만 두 개를 찾았다고 알려준다.
구체 클래스 타입으로 지정하여 주입받을 수 있지만, 이렇게 하는 경우 DIP가 위배되고 유연성이 떨어진다. 또한 이름만 다르고 똑같은 타입의 스프링 빈이 2개 이상 있을 때 해결할 수 없다.
조회 대상 빈이 2개 이상인 경우에 해결하는 방법은 여러 가지가 있다.
@Autowired
필드 명 매칭@Qualifier
와 @Qualifier
끼리 매칭, 빈 이름 매칭@Primary
매칭@Autowired
는 타입 매칭을 시도한다. 이때 여러 빈이 조회되면 필드 이름, 파라미터 이름으로 빈 이름 매칭을 시도한다.
아래처럼 필드 명이나 생성자의 파라미터 명을 통해 빈 이름을 매칭할 수 있다.
필드 명 매칭은 먼저 타입 매칭을 시도하고 여러 빈이 조회되면 추가로 동작하는 기능이다.
- 타입 매칭
- 타입 매칭의 결과가 여러 개일 때 필드 명, 파라미터 명으로 빈 이름 매칭
@Qualifier
는 추가 구분자를 부여하는 방법이다. 빈 이름이 변경되는 것은 아니다!
빈을 등록할 때 @Qualifier
어노테이션을 붙여주고 구분자 이름을 지정한다.
주입 시에도 @Qualifier
어노테이션을 붙여주고 주입할 빈의 구분자 이름을 입력한다.
만약
@Qualifier
를 통해 주입할 때 빈을 찾지 못한다면, 지정한 구분자 이름과 동일한 이름의 스프링 빈을 추가로 찾는다. 하지만@Qualifier
는@Qualifier
를 찾는 용도로 사용하는 것이 좋다.
@Qualifier
끼리 매칭- 빈 이름 매칭
NoSuchBeanDefinitionException
발생
@Primary
는 우선순위를 지정하는 방법이다. @Autowired
로 타입 매칭을 시도했을 때 여러 빈이 조회되면 @Primary
가 붙은 빈이 우선권을 가진다.
RateDiscountPolicy
에 @Primary
를 붙이면, RateDiscountPolicy
가 우선권을 갖게 되어 우선적으로 주입된다.
실무에서는, 코드에서 자주 사용되는 메인 데이터베이스의 커넥션을 획득하는 스프링 빈과 특별한 기능으로 가끔 사용하는 서브 데이터베이스의 커넥션을 획득하는 스프링 빈이 있는 경우, 메인 데이터베이스의 커넥션을 획득하는 스프링 빈은 @Primary
를 사용하고 서브 데이터베이스의 커넥션을 획득하는 스프링 빈은 @Qualifier
를 사용하여 명시적으로 획득하는 방식을 사용해 깔끔한 코드를 유지하는 경우도 있다고 한다.
@Qualifier
와@Primary
중에 어떤 것이 우선순위가 높을까? 스프링은 자동보다 수동, 넓은 범위의 선택권보다 좁은 범위의 선택권이 우선순위가 높기 때문에@Primary
보다@Qualifier
가 우선순위가 높다.