스프링에서 조회 대상 빈이 2개 이상일 때 해결 방법

빈이 2개 이상일 때 생기는 오류

스프링에서는 같은 타입의 빈이 여러 개일 때, 어떤 빈을 사용할지 모호성이 발생합니다.

예를 들어 @Autowired 는 타입으로 빈을 조회하기 때문에 interface 가 discountPolicy 인 구현체가 2개 이상이라면 오류가 발생합니다. 당연하게도 discountPolicy 로 만든 구현체가 하나여야 하는데 2개 이상이라서 어떤 구현체를 불러와야 할지 모르기 때문입니다.

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

@Component
public class RateDiscountPolicy implements DiscountPolicy {}

@Autowired
private final DiscountPolicy discountPolicy; // NoUniqueBeanDefinitionException 오류

 

이를 해결하기 위해 타입 매칭후 추가 조건을 지정하는 방법들을 제공합니다.

해결 방법

1. @Autowired 필드명 매칭

2. @Qualifier → @Qualifier 끼리 매칭 → 빈 이름 매칭

3. @Primary 사용

@Autowired 필드명 매칭

@Autowired 는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭합니다.

@Autowired
private DiscountPolicy discountPolicy;
                              ↓
private DiscountPolicy RateDiscountPolicy;

 

 

필드 명 매칭은 먼저 타입 매칭을 시도하고 그 결과에 여러 빈이 있을 대 추가로 동작하는 기능입니다.

 

@Qualifier

추가 구분자를 붙여주는 방법입니다.

주입 시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아닙니다.
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements discountPolicy {}

@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements discountPolicy {}

// 다른곳에서 주입 
@Autowired
public OrderServiceImpl(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy)

 

@Primary 

우선순위를 정하는 방법입니다.

@Autowired 시에 여러 빈이 매칭되면 @Primary 가 우선권을 가집니다.

@Component
@Primary
public class RateDiscountPolicy implements discountPolicy {}

@Component
public class FixDiscountPolicy implements discountPolicy {}

// 후에 의존성 주입

@Autowired
public OrderServiceImpl(DiscountPolicy discountPolicy) { // ... }

 

@Primary, @Qualifier 활용

코드에서 자주 사용하는 메인 데이터베이스의 커넥션을 획득하는 스프링 빈이 있고, 코드에서 특별한 기능으로 가끔 사용하는 서브 데이터베이스의 커넥션을 획득하는 스프링 빈이 있다고 가정할 때 메인 데이터베이스의 커넥션을 획득하는 스프링 빈은 @Primary 를 적용해서 조회하는 곳에서 @Qualifier 지정 없이 편리하게 조회하고, 서브 데이터베이스 커넥션 빈을 획득할 때는 @Qualifier 를 지정해서 명시적으로 획득하는 방식으로 사용하면 코드를 깔끔하게 유지할 수 있습니다.

 

우선순위

@Primary 는 기본값처럼 동작하는 것이고, @Qualifier 는 매우 상세하게 동작하게 됩니다. 

이런 경우 스프링은 자동보다는 수동이, 넓은 범위의 선택권 보다는 좁은 범위의 선택권이 우선순위가 높습니다. 따라서 여기서도 @Qualifier 가 우선권이 높습니다.

'Spring' 카테고리의 다른 글

JSON 형태로 객체 반환하기  (1) 2025.01.15
빈 생명주기 콜백  (1) 2025.01.09
다양한 의존관계 주입 방법  (1) 2025.01.07
Spring 웹 애플리케이션 계층구조  (3) 2024.12.23
Spring - @Value  (3) 2024.12.20