스프링 컨테이너에 빈을 등록하면 의존관계는 스프링 컨테이너가 알아서 맺어준다.
그런데 만약 동일 타입의 빈이 여러 개라면 스프링이 어떻게 구분을 해서 알맞은 빈을 주입할까?
문제 제기
public class SomeClass {
private final SomeInterface someBean;
@Autowired
public SomeClass(SomeInterface someBean) {
this.someBean = someBean;
}
// 사용할 메서드 등
}
위와 같은 의존성 주입 코드가 있다.
Spring은 IoC 컨테이너에서 SomeInterface
를 구현한 어떤 클래스의 인스턴스를 찾아서 빈을 검색하고 주입한다.
만약 여기서 SomeInterface
로 구현한 클래스가 2개 이상이라면 어떤 클래스의 인스턴스를 주입할까? (= 동일 타입의 빈이 여러 개라면)
@Primary
사용@Primary
어노테이션을 사용하면 특정 빈을 기본 빈으로 지정할 수 있다. @Primary
가 붙은 빈이 여러 개의 등록된 빈 중 가장 높은 우선순위를 가진다.
@Component
@Primary
public class PrimaryBean implements SomeInterface {
// Implementation
}
@Qualifier
사용@Qualifier 어노테이션을 사용하면 명시적으로 어떤 빈을 주입할지 지정할 수 있다.
@Component
@Qualifier("qualifier1")
public class QualifiedBean1 implements SomeInterface {
// Implementation
}
@Component
@Qualifier("qualifier2")
public class QualifiedBean2 implements SomeInterface {
// Implementation
}
public class SomeClass {
private final SomeInterface bean;
@Autowired
@Qualifier("qualifier1") // qualifier1을 사용하겠다고 지정
public SomeClass(SomeInterface bean) {
this.bean = bean;
}
// 사용할 메서드 등
}
👉 만약
@Primary
와@Qualifier
가 동시에 존재하면 우선순위는@Qualifier
에게 간다!!
빈의 이름을 직접 지정해 어떤 빈을 주입할지 명시적으로 지정한다.
@Component("specificBeanName")
public class SpecificBean implements SomeInterface {
// Implementation
}
public class SomeClass {
private final SomeInterface bean;
@Autowired
public SomeClass(@Qualifier("specificBeanName") SomeInterface bean) {
this.bean = bean;
}
// 사용할 메서드 등
}
@Component
: Spring의 컴포넌트 스캔 기능을 통해 스프링 컨테이너가 해당 클래스를 자동으로 빈(Bean)으로 등록하게 만드는 것@Component("specificBeanName")
와 같이 이름을 명시하면, 해당 빈의 이름을 specificBeanName으로 설정한다.➕ 위의 규칙들이 없으면 Spring은 다음과 같은 기본 규칙을 따른다.
@Primary
가 지정되지 않은 경우, 가장 최근에 등록된 빈이 주입될 수 있다.- 만약에도 결정이 불가하다면, Spring은
NoUniqueBeanDefinitionException
예외를 던진다.