[Spring] 같은 타입의 빈 문제 해결 방법(@Primary, @Qualifier)

2023. 2. 15. 21:57

스프링은 빈과 연관된 의존관계를 주입할 때 스프링 컨테이너에서 해당 빈을 조회해서 의존관계를 주입한다.

만약, 같은 타입의 빈이 두 개 이상 존재하면 스프링은 의존관계를 주입할 때 어떤 빈을 주입해야 할지 모르기 때문에 애플리케이션은 실행되지 않는다. 

 

Animal 인터페이스와 이를 구현한 Cat, Dog 클래스가 있고 AnimalService에서 Animal을 주입받는다고 가정하면 콘솔에 다음과 같이 나온다.

 

Animal

package hello.core.animal;

public interface Animal {}

Cat

package hello.core.animal;

import org.springframework.stereotype.Component;

@Component
public class Cat implements Animal{
}

Dog

package hello.core.animal;


import org.springframework.stereotype.Component;

@Component
public class Dog implements Animal{
}

AnimalService

package hello.core.animal;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class AnimalService {
    
    private final Animal animal;
    
}

 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in hello.core.animal.AnimalService required a single bean, but 2 were found:
	- cat: defined in file [~\Cat.class]
	- dog: defined in file [~\Dog.class]


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


Process finished with exit code 1

위와 같이 3가지 방법을 사용하라고 한다.

 

1. @Primary

@Primary는 우선순위를 지정하는 어노테이션이다. 

의존관계 주입 시 여러 개의 빈이 매칭되면 @Primay를 적용한 빈이 우선권을 갖게 된다.

 

@Primary
@Component
public class Dog implements Animal{
}

 

2. @Qualifier

@Qualifier는 추가 구분자를 붙여주는 방법이다. 별명처럼 추가적인 방법을 제공하는 것일 뿐 빈 이름을 변경하는 것이 아니다.

@Service
//@RequiredArgsConstructor
//롬복 사용시 @Qualifier를 사용하기 위해선 추가적인 설정이 필요하기 때문에 주석 처리
public class AnimalService {

    private final Animal animal;

    public AnimalService(@Qualifier("dogdog") Animal animal) {
        this.animal = animal;
    }
}

 

3. 여러 개의 빈을 한 번에 받기(updating the consumer to accept multiple beans)

의도적으로 여러 개의 빈이 필요할 때 사용한다.

스프링에서는 Collection 주입을 지원해 주기 때문에 같은 타입의 여러 빈이 존재하거나 필드나 파라미터 변수의 타입이 Collection, List, Map 일 경우 컬렉션으로 넘겨주어 한 번에 의존 관계를 맺게 해 준다.

@Slf4j
@Service
@RequiredArgsConstructor
public class AnimalService {

    private final Map<String,Animal> animal;

    @PostConstruct
    public void init() {
        log.info("animal = {}", animal);
    }
}

//animal = {cat=hello.core.animal.Cat@29138d3a, dog=hello.core.animal.Dog@5cbe2654}

 

참고 자료  : 김영한님 스프링 핵심 원리 - 기본편

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

BELATED ARTICLES

more