이번 시간에는 컴포넌트 스캔을 할 때, 중복 등록과 충돌에 대해서 알아보았다.
컴포넌트 스캔에서 같은 빈 이름을 등록한다면?
다음 두가지 상황이 있다.
1. 컴포넌트 스캔으로 자동 빈 등록 A와 자동 빈 등록한 B가 이름이 같은 경우.
2. 수동으로 빈 등록한 A와 자동 빈 등록한 B가 있는 경우.
1번의 경우, 결론부터 말하자면, ConflictingBeanDefinitionException 예외가 발생할 것이다.
직접 테스트를 해보기 위해 다른 서비스 클래스에 같은 이름을 부여했다.
AutoAppConfigTest에서 테스트를 돌려보면
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [hello.core.AutoAppConfig]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'service' for bean class [hello.core.order.OrderServiceImpl] conflicts with existing, non-compatible bean definition of same name and class [hello.core.member.MemberServiceImpl]
이런 오류가 발생한다. 쉽게 말해서 같은 이름의 빈이 충돌됐다~~
두번째로, 수동 빈 등록과 자동 빈 등록에서 빈 이름이 충돌된다면?
기존에 @Component를 통해 자동으로 등록 된 MemoryMemberRepository가 있고,
테스트를 위해서 수동으로 AutoAppConfig에 memoryMemberRepository 빈 객체를 추가해준다.
테스트를 돌려보면~~
테스트가 통과함. 그리고 로그중에 아래와 같은 부분이 있다.
Overriding bean definition for bean 'memoryMemberRepository' with a different definition: replacing [Generic bean: class [hello.core.member.MemoryMemberRepository];
같은 이름의 빈을 오버라이딩 했다는 것인데, 위와 같은 경우에는 수동 빈 등록이 우선권을 가진다.
즉, 수동 빈이 자동 빈을 오버라이딩 해버린다는 것이다.
보통 실무에서는 개발자가 의도적으로 수동 빈이 우선권을 가지는 점을 의도적으로 설정해서 하기 보다는,
여러가지 설정들이 꼬여서 이런 결과가 되는 경우가 대부분이라고 한다ㅋㅋㅋ 그러면 어려운 버그가 만들어진다.
그래서 최근 스프링 부트에서 수동 빈 등록과 자동 빈 등록이 충돌나면 오류가 발생하도록 기본값을 바꾸었다.
스프링 메인 클래스에서 실행을 해보면, 실행이 실패되면서 위와 같이 오류가 뜬다.
The bean 'memoryMemberRepository', defined in class path resource [hello/core/AutoAppConfig.class], could not be registered. A bean with that name has already been defined in file ....... and overriding is disabled.
스프링 부트에서 spring.main.allow-bean-definition-overriding 의 설정 기본값을 false로 해놨기 때문에,
오버라이딩이 안되는 것이 기본값이고 사용을 위해서는 properties에서 true로 셋팅을 해주면 된다.
이렇게 애매한 버그가 생기게 되면 잡기 힘들어지기 때문에, 명확하게 코딩하는 것이 중요하다.
댓글