FrameWork/Spring

[Spring] 의존 관계 자동 주입( Autometic Dependency Injection) - NoUniqueBeanDefinitionException

머지?는 병합입니다 2022. 7. 22. 00:21

 

조회 대상 빈이 2개 이상일 때는 NoUniqueBeanDefinitionException 예외가 발생하게 된다.

이 때는 3가지 해결 방법이 있다.

 

  1. @Autowired 필드명으로 매칭
  2. @Qualifier -> @Qualifier끼리 매칭 -> 빈 이름 매칭
  3. @Primary 사용

 

1️⃣ @Autowired

@Autowired 는 먼저 타입(Type)으로 Bean을 조회하게 되는데, 이때 동일 타입의 빈이 다수 있으면

필드 이름, 파라미터 이름으로 빈 이름을 추가 비교한다.

 

2️⃣ @Qualifier

    1. @Qualifier는 @Qualifier를 찾는 용도로만 사용하는게 명확하다

    2. 빈 이름 매칭

    3. 없으면 NoUniqueBeanDefinitionException  예외 발생

    4. 주입 받을 때, 모든 코드에 @Qualifier를 붙여주어야 한다는 단점이 있다.

    5. 치명적으로 @Qualifier(" ")안에 오타가 있을 시 컴파일시 타입 체크를 못한다.

        (@Qualifier 안 참조 메서드 이름이 String type으로 되어 있으므로)

        => 해결방법 : Annotation으로  만든다.

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier("mainSalesPolicy") 
public @interface MainSalesPolicy {
}
@Component
//@Qualifier("mainSalesPolicy") 
@MainSalesPolicy
public class ExtraSalesPolicy implements SalesPolicy {}

Annotation에는 상속이라는 개념이 없다.

이렇게 여러 Annotation을 모아 사용하는 기능은 스프링이 지원해주는 기능이다. 

@Qulifier 뿐만 아니라 다른 Annotation들도 함께 조합해서 사용할 수 있다.

 

 

3️⃣ @Primary

    1. @Autowired시, 빈이 여러개 매칭되면 @Primary가 붙은 것을 우선적으로 조회를 한다.

 

📢 우선 순위

@Primary는 기본값처럼 동작하는 것이고, @Qualifier 는 매우 상세하게 동작한다. 이런 경우 어떤 것이 우선권을 가져갈까? 스프링은 자동보다는 수동이, 넒은 범위의 선택권보다는 좁은 범위의 선택권이 우선 순위가 높다. 따라서 여기서도@Qualifier가 우선권이 높다.