프로젝트 진행할 때 "DB는 안 정해졌는데 언젠가 정해질것이니 개발을 하시오." 이런 상황을 겪어봤을 것이다..
Spring을 입문자라 이럴때면 주석처리를 해서 해결을 하는 나도 속터지고 너도 속터지는 방법을 사용해 개발을 했었다..🤬
그래서 오늘은 "같은 타입의 빈이 여러개일 때 어떻게 해야하는가?" 에 대해서 글을 써보려고 한다.
아주 간단하게 BookService
가 BookRepository
를 사용하고, BookRepository
구현체로 MyBookRepository
, YourBookRepository
클래스가 있다고 했을때 Spring은 어떤 클래스를 주입을 해줄까?
@Service
public class BookService {
@Autowired
BookRepository bookRepository;
}
public interface BookRepository {}
@Repository
public class MyBookRepository implements BookRepository {}
@Repository
public class YourBookRepository implements BookRepository {}
MyBookRepository, YourBookRepository 빈이 2개가 존재하는데 둘 중 어떤 것을 원하는지 Spring은 알 수 없어서 주입을 해주지 못했다.
이를 해결하기 위한 추천하는 액션으로는 3가지가 있다. 라고 적혀있다.
그럼 이 3가지 방법을 좀 더 살펴보자.
우리는 MyBookRepository
를 사용하고 싶다고 가정을 하자.
@Repository
@Primary // 추가!
public class MyBookRepository implements BookRepository {}
@Repository
public class YourBookRepository implements BookRepository {}
MyBookRepository
클래스에 @Primary
를 붙이면 "여러가지 BookRepository가 있지만 주입할 때는 얘를 주입해라!" 라고 우선순위를 부여한다. 그럼 BookService
에서는 BookRepository
를 주입할때 @Primary
가 붙어있는 애를 주입을 해주게 된다.
여기서 주의할 점은 MyBookRepository
에 @Primary
를 붙인 상태에서 잊어먹고 YourBookRepository
에도 @Primary
를 붙이게 된다면
"아니 뭔 primary가 너도 나도 다 붙어있어. 배째~" 라는
"more than one 'primary' bean found among candidates: [myBookRepository, yourBookRepository]" 이러한 에러를 볼 수 있으니 잘 확인해서 사용해야한다.
이 방법은 어디에 사용하는지 모르겠지만 일단 이런 방법이 있다 정도로 알고 넘어가려고 한다.
아래와 같이 작성하면 BookRepository
에 해당하는 한개면 한개, 두개면 두개 이렇게 모든 bean을 주입받을 수 있다. 우리는 MyBookRepository
와 YourBookRepository
로 총 2개를 주입받는다.
@Service
public class BookService {
@Autowired
List<BookRepository> bookRepository; //List로 전부 다 주입!
public void printBookRepository() {
this.bookRepository.forEach(System.out::println);
}
}
이 방법보단 @Primary
사용하는 것을 추천한다.
Qualifier(bean ID)
로 작성하면 되는데 bean의 ID는 보통 클래스의 스몰케이스와 같다.
@Service
public class BookService {
@Autowired
@Qualifier("myBookRepository") //빈 이름에 맞는 클래스를 찾음
BookRepository bookRepository;
}
@Autowired
는 타입을 먼저 보고 이름도 확인한다.
myBookRepository
주입 받고 싶다면 주입 받을 빈의 이름과 동일하게 field 이름을 맞춰주면 여러개의 타입중에 필드이름하고 동일한 빈을 주입 받아서 사용한다.
@Service
public class BookService {
@Autowire
BookRepository myBookRepository; //난 MyBookRepository 주입받고싶어
public void printBookRepository() {
System.out.println(myBookRepository.getClass());
}
}
같은 타입의 빈이 여러개일 때 어떻게 해결하는지에 대해 살펴봤다.
그러니 앞으로 주석으로 해결하는 삐리리 같은 방법은 사용하지 말자. 💩
이 글은 백기선님 유료 강의를 수강하고 참고하여 작성한 글입니다.