인프런 커뮤니티 질문&답변
"중복 등록과 충돌" 강의에서 강사님과 다른 에러가 발생합니다.
작성
·
12
·
수정됨
0
spring.main.allow-bean-definition-overriding=true
07:05~ 부분에서 위 코드를 작성하면 스프링 부트 애플리케이션을 에러가 발생하지 않는 모습을 보여주셨는데요.
20:53:29.311 [main] DEBUG o.s.b.d.LoggingFailureAnalysisReporter --Application failed to start due to an exception
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'drj9812.spring.member.MemberRepository' available: expected single matching bean but found 2: memoryMemberRepository,memberRepository
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1739)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1651)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:912)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:240)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1382)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1221)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1218)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1184)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1121)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:983)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:620)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:765)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:454)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1374)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at drj9812.spring.Application.main(Application.java:10)
20:53:29.311 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter --
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in drj9812.spring.member.MemberServiceImpl required a single bean, but 2 were found:
- memoryMemberRepository: defined by method 'memberRepository' in class path resource [drj9812/spring/AutoAppConfig.class]
- memberRepository: defined by method 'memberRepository' in class path resource [drj9812/spring/AppConfig.class]
This may be due to missing parameter name information
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
Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)저의 경우엔 위와 같은 에러가 발생합니다.
강사님과 다르게 저는 에러가 발생한 이유가 무엇인가요?
로그 내용을 보아
AutoAppConfig과AppConfig이 충돌이 난 것 같은데, 이미AutoAppConfig에서excludeFilters로AppConfig은 스캔하지 않도록 설정했으니 에러가 발생하지 않아야 되는 거 아닌가요?
답변 2
0
안녕하세요, 인프런 AI 인턴입니다. drj9812님께서 스프링 빈 충돌 문제에 대해 질문을 주셨습니다. 현재 주신 로그에는 NoUniqueBeanDefinitionException 에러가 나타나고 있습니다. 이는 스프링 컨테이너에서 동일한 타입의 빈이 두 개 이상 등록된 경우 발생하는 에러입니다.
문제의 원인
- 빈 중복 등록:
AutoAppConfig와AppConfig둘 다MemberRepository타입 빈을 등록하고 있어서 발생하는 문제인 것 같습니다.
- excludeFilters 오작동:
excludeFilters가 설정되었더라도,AppConfig의 빈 등록 메서드가 접근 가능한 경로에 있을 경우 자동 실행될 수 있습니다. 스프링이 어떤 방식으로 코드를 해석하거나, 프로젝트 셋업에 따라 다르게 동작할 수 있습니다.
해결 방안
- 빈 우선순위 설정: 두 빈 중 하나를 기본으로 사용하게 하려면
@Primary어노테이션을 사용하여 기본 빈을 지정하여 충돌을 해결할 수 있습니다.
@Bean
@Primary
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
- @Qualifier 사용: 특정 빈을 주입받기 위해
@Qualifier를 사용하여 명확하게 어떤 빈을 주입받을 것인지 지정할 수 있습니다.
@Autowired
public MemberServiceImpl(@Qualifier("memoryMemberRepository") MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
Configuration 클래스 정리:
AppConfig또는AutoAppConfig중 하나에서만 해당 빈을 등록하도록 구조를 정리할 수 있습니다. 서로 다른 부트스트랩 사이클로 인해 특정 빈이 예상치 못하게 등록되는 것을 방지할 수 있습니다.빈 이름 변경: 빈 이름을 다르게 설정하여 중복을 피할 수 있습니다.
아래의 링크는 스프링 빈 중복 등록과 관련된 문제 해결 방법을 설명하는 유사한 질문들입니다:
- 스프링 빈 중복 등록 해결 방법
- 빈 등록 시 주의할 점
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
0
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
@Configuration
@ComponentScan(
basePackages = "drj9812.spring.member",
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
@Bean(name = "memoryMemberRepository")
MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
@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 selectByMemberId(Long memberId) {
return store.get(memberId);
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}제 코드입니다.





