Dev/Spring
같은 타입의 Bean이 두 개일 때
마라탕천재
2024. 8. 25. 18:04
1. 같은 타입 Bean 등록
Food를 상속받은 Chicken과 Pizza 클래스를 빈으로 등록한다.
- Food 클래스
public interface Food {
void eat();
}
- Chicken 클래스
@Component
public class Chicken implements Food {
@Override
public void eat() {
System.out.println("치킨을 먹습니다.");
}
}
- Pizza 클래스
@Component
public class Pizza implements Food {
@Override
public void eat() {
System.out.println("피자를 먹습니다.");
}
}
- 테스트 코드 작성
같은 타입의 빈이 두 개라서 다음과 같이 오류가 발생할 것이다.
Autowired를 통해 의존성을 주입하려고 시도하고있으나, 빈으로 등록된 Chicken과 Pizza중 어떤 클래스를 주입해야 할 지 몰라서 발생하는 오류이다.
@SpringBootTest
public class BeanTest {
@Autowired
Food food;
}
2. Bean 이름 명시
빈 이름을 명시하면 해결할 수 있다.
단, 이 경우에 주입받는 객체의 이름은 해당 클래스명을 캐멀케이스 방식으로 작성해야 한다.
- 테스트 코드 변경
@SpringBootTest
public class BeanTest {
@Autowired
Food pizza;
@Autowired
Food chicken;
@Test
void test1() {
pizza.eat();
chicken.eat();
}
}
3. @Primary 어노테이션 이용
- Chicken 클래스에 @Primary어노테이션 추가
- 테스트 코드 변경
@SpringBootTest
public class BeanTest {
@Autowired
Food food;
@Test
void test1() {
food.eat();
}
}
@Primary가 추가되면 같은 타입의 Bean이 여러 개 있더라도 우선 @Primary가 설정된 Bean 객체를 주입해준다.
4. @Qualifier 어노테이션 이용
- Pizza 클래스에 @Qualifier 어노테이션 추가
@Component
@Qualifier("pizza")
public class Pizza implements Food {
@Override
public void eat() {
System.out.println("피자를 먹습니다.");
}
}
- 테스트 코드 변경
@SpringBootTest
public class BeanTest {
@Autowired
@Qualifier("pizza")
Food food;
@Test
@DisplayName("Primary 와 Qualifier 우선순위 확인")
void test1() {
// 현재 Chicken 은 Primary 가 적용된 상태
// Pizza는 Qualifier 가 추가된 상태입니다.
food.eat();
}
}
Qualifier는 적용하기 위해서 주입 받고자하는 곳에 해당 Qualifier를 추가한다.
같은 타입의 Bean들에 Qualifier와 Primary가 동시에 적용되어있다면 Qualifier의 우선순위가 더 높다.
따라서, 같은 타입의 Bean이 여러 개 있을 때는 범용적으로 사용되는 Bean 객체에는 Primary를 설정하고 지엽적으로 사용되는 Bean 객체에는 Qualifier를 사용하는 것이 좋다.