Bean에 우선순위 부여하기
context.getBean(Person.class)
위 코드를 통해 Bean으로 만들어진 Person 클래스를 호출할 수 있었습니다.
(Person를 반환 유형으로 가진 클래스)
그러나 Person를 반환하는 클래스가 여럿이라면 오류가 발생합니다.
(조건에 일치하는 후보가 여러 개인 시나리오에서 예외를 출력합니다)
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.ride.learnspringframework.Person' available: expected single matching bean but found 3: person,person2MethodCall,person3Parameters
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1310)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1191)
at com.ride.learnspringframework.AppHelloWorldSpring.main(AppHelloWorldSpring.java:26)
따라서 오류가 발생하지 않도록 클래스를 호출하지 않고 이름으로 호출하거나,
추가적인 설정이 필요합니다.
하나를 기본으로 만들거나, 한정자를 만듭니다.
1. @Primary
하나를 @Primary를 사용하여 default로 만듭니다
@Bean
@Primary
public Person person4Parameters(String name, int age, Address address) {
return new Person(name, age, address);
}
context.getBean(Person.class)
이제 예외가 발생하지 않습니다.
2. @Qualifier("이름")
Bean에 @Qualifier를 추가하고 호출 시 @Qualifier("이름")를 붙여서 Bean끼리 연결합니다.
@Bean(name = "address3")
@Qualifier("address3qualifier")
public Address address3() {
var address = new Address("street3", "city3");
return address;
}
@Bean
public Person person5Qualifier(
String name,
int age,
@Qualifier("address3qualifier") Address address) {
return new Person(name, age, address);
}
이제 예외가 발생하지 않습니다.


public class AppProgramBeans {
public static void main(String[] args) {
try (
var context =
new AnnotationConfigApplicationContext
(ProgramConfiguration.class);
) {
context.getBean(Console.class).up();
context.getBean(ProgramRunner.class).run();
}
}
}
@Configuration
public class ProgramConfiguration {
@Bean
public Console program() {
var program = new Game();
return program;
}
@Bean
public ProgramRunner programRunner(Console program) {
var programRunner = new ProgramRunner(program);
return programRunner;
}
}
Spring은 객체를 관리하며 AutoWiring 수행합니다.
Spring은 자동으로 객체를 생성하고 연결합니다.
특정 클래스의 인스턴스 생성을 Spring에 요청하려면 (@Component)어노테이션을 추가해야 합니다.
@Component를 추가한 클래스는 어노테이션 기반의 Configuration과 클래스패스 스캐닝을 사용할 때,
자동감지에 대한 후보로 간주됩니다.
(@ComponentSacn 을 사용하여 @Component 클래스를 감지할 수 있게 해줍니다 - 패키지를 지정할 수도 있습니다)
따라서 결국 Spring이 우리에게 특정 인스턴스를 생성해줍니다.
(Spring이 Bean을 생성하게 할 수도 있습니다)
@ComponentScan으로 @Component 클래스를 스캐닝하여 선택합니다.
@Configuration
@ComponentScan("com.ride.learnspringframework2.game")
public class AppProgramBeans {
public static void main(String[] args) {
try (
var context =
new AnnotationConfigApplicationContext
(AppProgramBeans.class);
) {
context.getBean(Console.class).up();
context.getBean(ProgramRunner.class).run();
}
}
}
Console 클래스와 ProgramRunner 클래스에 @Component를 추가하면,
@ComponentScan이 작동하면서 @Component클래스를 스캐닝하고
Bean 객체로 생성되며 연결됩니다.
(Bean 객체로 생성하기 위해 @Component를 기입해야 합니다)
(AutoWiring을 수행합니다)
@Configuration 클래스를 생성하지 않아도 됩니다.
Spring은
@ComponentScan을 사용하여 @Component를 스캐닝하여
객체를 관리하고 AutoWiring을 수행할 뿐만 아니라 객체를 생성해줍니다.
Spring은
지정된 패키지를 스캔하고, 컴포넌트를 찾아 인스턴스를 생성합니다.
이를 AutoWiring하여 전체 애플리케이션을 제대로 작동시켜 줍니다.
@Component 클래스에서 @Primary @Qualifier 중 어떤 것을 사용해야 할까요?
@Primary
여러 후보가 자격이 있는 경우, @Primary Bean에게 우선권을 줍니다.
@Qualifier
지정된 Bean을 AutoWiring 합니다.
@Component @Primary
class QuickSort implements SortAlgorithm {}
@Component
class BubbleSort implements SortAlgorithm {}
@Component @Qualifier("RadixSortQualifier")
class RadixSort implements SortAlgorithm {}
@Component
class ComplexAlgorithm
@Autowired
private SortingAlgorithm algorithm; // QuickSort
@Component
class AnotherComplexAlgorithm
@Autowired @Qualifier("RadixSortQualifier")
private SortingAlgorithm iWantToUseRadixSortOnly; // RadixSort
@Component
class RadixSort implements SortAlgorithm {}
@Component
class AnotherComplexAlgorithm
@Autowired @Qualifier("radixSort") // 메서드 이름으로 호출 가능(첫번째 문자는 소문자로)
private SortingAlgorithm iWantToUseRadixSortOnly; // RadixSort
@Primary, @Qualifier를 사용할 때, 의존성을 사용하는 클래스의 관점에서 생각해야 합니다.
그리고, @Qualifier가 @Primary보다 더 높은 우선순위를 갖고 있다는 점을 기억해야 합니다.
@Component
class QuickSort implements SortAlgorithm {}
@Component
class BubbleSort implements SortAlgorithm {}
@Component
class ComplexAlgorithm
@Autowired
private SortingAlgorithm algorithm; // Spring이 런타임 중에 적합한 것을 자동으로 선택