스프링부트를 사용하면서, 나는 주로 다음과 같은 형태로 클래스를 만들어둔다.
Repository나 Service는 인터페이스를 만들어두고 구현 클래스를 정의해서 사용하는 편이다.
그 다음, 의존성 주입 과정에서 구현 클래스가 아닌, 인터페이스를 타입으로 두어 받아도 구현 클래스가 주입된다. DIP도 만족하는 좋은 설계다!
이 때, 만약 인터페이스를 구현한 클래스가 하나가 아니라면 어떻게 될까?
위와 같이 구현 클래스를 추가로 만들었다.
이후 실행해보자.
그러자 Exception이 발생하고 프로그램이 종료되었다. 오류 내용은 single bean이 필요하지만 2개가 발견되었다는 오류다.
밑에 나와있는 Action을 자세히 봐보자.
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
한개의 빈에 @Primary
애노테이션을 붙여준다. 이러면 @Primary가 붙은 빈이 우선권을 갖는다.
@Repository @Primary
public class TestAnswerRepository implements AnswerRepository{
...
먼저 빈 자체에 다음과 같이 애노테이션을 붙여준다.
@Repository @Qualifier("testBean")
public class TestAnswerRepository implements AnswerRepository{
여기서 @Qualifier
안에 들어가는 문자열은, 이후 식별자로 사용된다.
다음, DI를 받을 클래스에서도 @Qualifier
를 선언해준다.
@Autowired @Qualifier("testBean")
private AnswerRepository answerRepository;
(필드 주입 방법)
private final AnswerRepository answerRepository;
public AnswerService(@Qualifier("testBean") AnswerRepository answerRepository) {
this.answerRepository = answerRepository;
}
(생성자 주입 방법)
단, 주의할점은 Lombok의 @RequiredArgsConstructor
를 사용 할 때는 다음과 같이 사용해선 안된다.
@Qualifier("testBean")
private final AnswerRepository answerRepository;
인텔리제이에서도 다음같은 경고를 띄운다.
Lombok을 사용해서 편하게 생성자 주입을 할때, @Qualifier
는 적용되지 않는다.
컬렉션을 사용해서 여러 빈을 한번에 받을 수 있다.
@Autowired
private List<AnswerRepository> answerRepository;
글 잘 봤습니다.