개발/Spring

[Spring DI] 4. getBean() 메서드 사용과 Bean 관련 Exception 정리

nova_dev 2020. 11. 8. 20:05
반응형

Spring
getBean() 메서드 사용과 Bean 관련 Exception 정리

NoSuchBeanDefinitionException: No bean named 'versionPrint2' available
NoSuchBeanDefinitionException No qualifying bean of type 'spring.MemberPrinter' available

BeanNotOfRequiredTypeException

 

 getBean() 메서드 사용과 Bean관련 Exception 정리

앞에서 Bean 객체를 구할 때에는 getBean()메서드를 이용했다. (혹은 Autowired를 통해 자동으로 빈 객체를 받아왔다.) Autowired를 사용해도 내부적으로 Bean 객체를 호출하며 아래와 같이 NoSuchBeanDefinitionException 같은 것을 볼 수 있는데 왜 이런 문제가 발생하는지 알아보자.

VersionPrinter versionPrinter = ctx.getBean("versionPrinter", VersionPrinter.class)

위와 같이 getBean메서드를 이용하여 빈 객체를 받아 올 수 있는데 메서드의 첫 번째 인자는 빈의 이름이고, 두 번째 인자는 빈의 타입이다. 이 때 getBean() 메서드를 호출할 때 존재하지 않는 빈 이름을 사용하면 익셉션이 발생한다. 예를 들어 "versionPrinter"를 가져와야 하는데 "versionPrinter2"로 잘못 작성했을 경우, 아래와 같은 Exception을 볼 수 있다.

Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'versionPrinter2' available

NoSuchBeanDefinitionException: No bean named 'versionPrint2' available 의 내용을 해석하자면, versionPrinter2인 이름의 빈이 사용 가능하지 않다는 의미인데, 이를 통해 getBean() 메서드에 전달된 빈의 이름이 잘못 되었음을 알 수 있다.

[ ]

만약 빈의 실제 타입과 getBean() 메서드에 지정한 타입이 다르면 어떻게 될까? 이름이 listPrinter인 빈 타입이 MemberListPrinter인데 다음이 getBean() 메서드에 VersionPrinter 클래스를 전달했다고 하자.

VersionPrinter versionPrinter = ctx.getBean("listPrinter", VersionPrinter.class);

이 경우 발생하는 익셉션은 다음과 같다.

Exception in thread "main"
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'listPrinter' is excepted to be of type 'spring.VersionPrinter' 
but was actually of type 'spring.MemberListPrinter'

BeanNotOfRequiredTypeException: Bean named 'listPrinter' is excepted to be of typeBeanNotOfRequiredTypeException:  Bean named 'listPrinter' is excepted to be of type 'spring.VersionPrinter'  but was actually of type 'spring.MemberListPrinter'

에러 메세지는 'listPrinter'의 타입으로 VersionPrinter 타입을 기대했는데 실제 타입은 MemberListPrinter라는 사실을 알려주고 있다.

다음과 같이 빈 이름을 지정하지 않고 타입만으로 빈을 구할 수도 있다.

VersionPrinter versionPrinter = ctx.getBean(MemberPrinter.class)

이 때 해당 타입의 빈 객체가 한 개만 존재하면 해당 빈을 구해서 리턴한다. 해당 타입의 빈 객체가 존재하지 않으면 다음과 같은 익셉션이 발생한다.

Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'spring.MemberPrinter' available

NoSuchBeanDefinitionException:  No qualifying bean of type 'spring.MemberPrinter' available

같은 타입의 빈 객체가 두 개 이상 존재할 수도 있다. 예를 들어 설정 클래스에 다음과 같이 타입이 VersionPrinter인 빈을 두 개 설정했다고 하자.

@Configuration
public class AppCtx {
	... // 생략
	@Bean
	public VersionPrinter versionPrinter() {
		VersionPrinter versionPrinter = new VersionPrinter();
		versionPrinter.setMajorVersion(5);
		versionPrinter.setMinorVersion(0);
		return versionPrinter;
	}
    @Bean
	public VersionPrinter oldVersionPrinter() {
		VersionPrinter versionPrinter = new VersionPrinter();
		versionPrinter.setMajorVersion(4);
		versionPrinter.setMinorVersion(3);
		return versionPrinter;
	}
}

이 경우 ctx.getBean(VersionPrinter.class) 메서드를 실행하면 다음과 같은 익셉션이 발생한다.

Exception in thread "main"
ord.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'spring.VersionPrinter' available: 
expected single matching bean but found 2: versionPrinter.oldVersionPrinter

이 익셉션은 VersionPrinter 타입의 빈을 구하려 하는데, 해당 타입의 빈이 한 개가 아니고 두 개 (이름이 versionPrinter인 빈과 oldVersionPrinter인 빈) 존재한다는 내용을 보여준다.

 

관련글

위 글은 스프링5 프로그래밍 입문 (저자: 최범균) 책을 공부하면서 작성한 글입니다. (링크)

[스프링 DI] 1. 스프링 DI(Dependency Injection)란? (
링크)
[스프링 DI] 2. Spring DI 설정 (링크)
[스프링 DI] 3. Spring에서 두 개 이상의 설정 파일 이용하기 (링크)
[스프링 DI] 4. getBean() 메서드 사용과 Bean 관련 Exception 정리 (링크)

 
 

 

 

반응형