본문 바로가기
스프링/핵심 원리

[Spring] 조회 Bean이 2개 이상 발생하는 문제

by drCode 2022. 2. 22.
728x90
반응형

@Autowired 는 타입(Type)으로 조회한다.

@Autowired
private DiscountPolicy discountPolicy;

 

타입으로 조회하기 때문에, 마치 다음 코드와 유사하게 동작한다. (실제로는 더 많은 기능을 제공한다.)

'ac.getBean(DiscountPolicy.class)'

 

스프링 빈 조회(https://drcode-devblog.tistory.com/330)에서 학습했듯이 타입으로 조회하면 선택된 빈이 2개 이상일 때 문제가 발생한다.

'DiscountPolicy' 의 하위 타입인 FixDiscountPolicy, RateDiscountPolicy 둘다 스프링 빈으로 선언해보자.

 

FixDiscountPolicy.java

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class FixDiscountPolicy implements DiscountPolicy {

    private int discountFixAmount = 1000; // 1000원 할인

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        } else {
            return 0;
        }
    }
}

 

일단 그 전에 test 디렉토리 전체를 테스트 해보자

 

 

테스트를 돌리고 나면 위와 같은 에러가 발생한 것을 알 수 있다.

 

configurationTest() 를 보면  NullBean 이라고 나와있다.

 

AppConfig.java

@Configuration  // : ==> 설정정보
public class AppConfig {
    @Bean  
    public MemberService memberService() {
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemoryMemberRepository memberRepository() {
        System.out.println("call AppConfig.memberRepository");
        return new MemoryMemberRepository(); // DBRepository로 바뀔때 여기만 바꾸면 된다.
    }

    @Bean
    public OrderService orderService() {
        System.out.println("call AppConfig.orderService");
        return new OrderServiceImpl(memberRepository() , discountPolicy());
//        return null;
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();  // RateDiscountPolicy로 바꿀때 여기만 바꾸면 된다.
    }
}

 

return null을 주석처리하고 return new OrderService()를 활성화하면 다시 정상적으로 test가 된다.

 

 

모든 테스트 케이스가 정상적으로 통과되었다.

 

FixDiscountPolicy.java

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;
import org.springframework.stereotype.Component;

@Component
public class FixDiscountPolicy implements DiscountPolicy {

    private int discountFixAmount = 1000; // 1000원 할인

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        } else {
            return 0;
        }
    }
}

@Component 애노테이션을 붙여주고 test를 해보자

 

basicScan() 에서 오류가 발생한다. 왜그럴까?

 

 

FixDiscountPolicy 뿐만 아니라 RateDiscountPolicy가 @Component로 인해 빈으로 등록되어있기 때문이다

 

여기서 NoUniqueBeanDefinitionException은 종종 자주 만나게 될 수 있는 오류이다.

 

오류 메시지가 친절하게도 하나의 빈을 기대했는데, fixDiscountPolicy, rateDiscountPolicy 2개가 발견되었다고 알려준다.

 

이때 하위 타입으로 지정할 수도 있지만, 하위 타입으로 지정하는 것은 DIP를 위배하고 유연성이 떨어진다. 그리고 이름만 다르고, 완전히 똑같은 타입의 스프링 빈이 2개 있을 때 해결이 안된다.

스프링 빈을 수동 등록해서 문제를 해결해도 되지만, 의존 관계 자동 주입에서 해결하는 여러 방법이 있다.

 

728x90
반응형

댓글