Tech/Spring

[스프링 핵심 원리] 빈 중복 등록과 충돌

0m1n 2022. 1. 15. 14:24
728x90
반응형

컴포넌트 스캔에서 같은 빈 이름을 등록하게 되는 경우 충돌이 발생할까?

 

아래와 같이 2가지 상황이 있다고 하자.

 

  • 자동 빈 등록 vs 자동 빈 등록
  • 수동 빈 등록 vs 자동 빈 등록

1. 자동 빈 등록 vs 자동 빈 등록

역시 충돌이 나며, 에러를 발생시킨다.

 

2. 수동 빈 등록 vs 자동 빈 등록

헷갈릴 수 있는 부분이다. 테스트를 해보자!

 

AutoAppConfig 파일에 아래와 같이 다른 빈을 등록한다.

public class AutoAppConfig {
    @Bean(name = "memoryMemberRepository")
    MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

 

MemoryMemberRepository 에는 역시 다른 빈이 등록된다.

(자동 빈 등록 시 앞에 대문자는 소문자로 변환된다!)

@Component // memoryMemberRepository
public class MemoryMemberRepository implements MemberRepository{

}

 

그 후 테스트를 해보면 에러는 발생하지 않으며 아래와 같은 메시지가 나타난다.

Overriding bean definition for bean 'memoryMemberRepository' with a different definition: replacing [Generic bean: class [hello.core.member.MemoryMemberRepository]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [C:\Coding\core\core\out\production\classes\hello\core\member\MemoryMemberRepository.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=autoAppConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AutoAppConfig]

 

즉. 이 경우 수동 등록 빈이 우선권을 가진다!

 

하지만 이렇게 되면 여러 협업에서 개발에 꼬일 확률이 높아 어려운 버그가 만들어지게 된다.

따라서 최근 스프링 부트에서는 수동 빈 등록과 자동 빈 등록이 충돌 시 오류가 발생되도록 기본 값을 바꾸었다.

 

한번 스프링 부트로 테스트해보자.

 

CoreApplication에서 스프링 부트로 테스트해보면 에러가 발생하고 메시지가 발생한다.

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 [C:\Coding\core\core\out\production\classes\hello\core\member\MemoryMemberRepository.class] and overriding is disabled.

 

이미 정의가 되어 있다는 메시지이다! 또한 아래 메시지를 알려준다.

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

application.properties 파일에 spring.main.allow-bean-definition-overriding=true 를 복붙해서 원하는 대로 설정할 수 있다.

(true : 에러, false : 에러x)

 

결론적으로, 개발을 할때 항상 애매한 상황을 만들지 말자!

728x90
반응형