AppConfig의 @Bean 메서드의 이름을 아무렇게나 지으면 안되나요?
300
작성한 질문수 4
@Configuration
public class AppConfig {
@Bean
public MemoryMemberRepository memoryRepository() {
return new MemoryMemberRepository();
}
@Bean
public RateDiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memoryRepository());
}
@Bean
public OrderService orderService(){
// return null;
return new OrderServiceImpl(memoryRepository(), discountPolicy());
}
}
저는 지금까지 위의 코드처럼 MemoryMemberRepository 빈 객체를 생성하는 메서드의 이름을 memberRepository가 아니라 memoryRepository로 이름지어주고 진행해왔습니다.
그러다가 7.의존관계 자동 주입 챕터에서 test 폴더를 전부 테스트할 때
CoreApplicationTests에서 동일한 타입에 여러 Bean이 생성되었다는 오류 메시지를 받았습니다.
Parameter 0 of constructor in hello.core.member.MemberServiceImpl required a single bean, but 2 were found:
- memoryMemberRepository: defined in file [C:\Users\***\***\coding\source_code\Spring\inflearn2\out\production\classes\hello\core\member\MemoryMemberRepository.class]
- memoryRepository: defined by method 'memoryRepository' in class path resource [hello/core/AppConfig.class]
///
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'hello.core.member.MemberRepository' available: expected single matching bean but found 2: memoryMemberRepository,memoryRepository
해결하려는 과정에서 강의노트에 메서드 이름이 memberRepository였다는걸 알게됐고 이걸로 이름을 고쳐주고 다시 테스트하니까 정상적으로 테스트가 완료됐습니다.
메서드 이름만 바꿔준 것만으로 NoUniqueBean 오류가 해결된 이유가 궁금해졌습니다.
이것저것 코드를 건드렸는데 @Component 코드들을 아래에 붙이겠습니다. 감사합니다.
@Component
public class MemberServiceImpl implements MemberService{
private MemberRepository store;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository){
this.store = memberRepository;
}
@Override
public void register(Member newMember) {
store.save(newMember);
}
@Override
public Member search(Long memberId) {
return store.findById(memberId);
}
}
@Component
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
System.out.println("Constructor DI");
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}@Component
public class RateDiscountPolicy implements DiscountPolicy{
private static final double DISCOUNT_RATE = 0.1;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP)
return (int) (price * DISCOUNT_RATE);
else
return 0;
}
}
답변 1
0
안녕하세요, 인프런 AI 인턴이에요.
@Bean으로 등록된 메서드는 해당 메서드의 이름을 빈의 이름으로 사용합니다. 따라서, 메서드의 이름을 아무렇게나 지으면 안되고, 해당 빈을 가져다 쓸 때 메서드 이름으로 호출해야 합니다.
예를 들어, 위의 코드에서 memoryRepository() 메서드는 MemoryMemberRepository 타입의 빈을 생성하는 메서드입니다. 그래서 memberService()와 orderService() 메서드에서 이 빈을 사용하기 위해서는 메서드 이름으로 호출해야 합니다.
만약, 메서드의 이름을 memoryRepository 대신 다른 이름으로 지정한다면, 해당 이름으로 호출하면 메서드를 찾을 수 없기 때문에 NoSuchBeanDefinitionException 오류가 발생할 수 있습니다.
또한, 같은 타입의 빈이 여러 개 존재하는 경우에는 @Qualifier 애노테이션을 사용하여 어떤 빈을 주입할지 명시해야 합니다.
따라서, 수정 전 코드 상태에서는 bean의 이름을 memoryRepository로 바꿔줘야 합니다.
코드 자료
0
50
2
구현체가 동적으로 정해질 때, 팩토리 기법을 사용하나요?
0
56
2
MemberService의 인터페이스를 왜 사용하는지 궁금합니다.
0
78
1
롬복 @Setter를 써야 하는 상황이 있는건가요?
0
93
1
빈 등록 메서드의 파라미터가 빈이 아니어도 되나요?
0
81
1
테스트 속도가 나중에 영향이 있을까요?
0
77
1
gradle 설정 안떠서 질문 남깁니다!
0
122
2
build.gradle로 프로젝트를 여는 이유
0
87
1
provider 사용하는 이유
0
91
1
다음 강의 뭘 들어야 할까요
0
126
2
프로토타입 빈, 직접 destroy 호출 안 할 경우
0
66
1
beanB
0
82
2
퀴즈다시풀기
0
69
1
Gradle로 바꿔도 오류가 똑같이 발생하네요 ㅠㅠ
0
92
2
"중복 등록과 충돌" 강의에서 강사님과 다른 에러가 발생합니다.
0
67
3
run 실행했는데 결과창이 이렇게 뜨네요 왜 그런건가요>
0
106
2
도메인의 정의?
0
59
1
ApplicationContext 질문입니다.
0
63
1
@Scope의 proxyMode를 사용할때 단위 테스트 방법
0
91
2
ai api 선정하기 관련 질문
0
119
2
생성자 자동주입 관련해서
0
66
1
생성자 직접 호출 vs 팩토리 메서드 패턴
0
97
2
Spring에서 SessionScope와 RequestScope는 함께 사용되나요?
1
66
1
12:25
0
79
2





