스프링 properties 사용시 UnsatisfiedDependencyException 발생 원인
서버를 기동하던 중에 UnsatisfiedDependencyException이 발생하면서 BeanCreationException예외가 발생하였습니다. BeanCreationException은 말그대로 스프링빈 객체 생성중에 특정 예외가 발생하여 빈 생성이 되지 못할때 던져지는 예외입니다. 예외클래스명에도 나와있듯이 원인은 명확한데, 특정 필드에 의존주입이 되어 있을것으로 예상했지만 의존주입에 실패했기 때문에 발생하는 것입니다.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DataSourceConfig': Unsatisfied dependency expressed through field 'dbProp'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DatabaseInfoProperties': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'erp.db.name' in value "${erp.db.name}"
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
      at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DatabaseInfoProperties': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'erp.db.name' in value "${erp.db.name}"
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
...
cs


저의 경우에는 프로젝트에서 ERP시스템 측 DB에 연동하기 위해 DataSource를 설정하는 과정에서 DB 정보를 .properties 파일로 정의해두고 @Value 어노테이션을 통해 값을 주입받아 사용하는편입니다. DataSourceCoinfig 라는 스프링 Java Config 클래스를 만들어 DataSource 빈을 정의하는데, 여기서 DB 연결 정보를 DatabaseInfoProperties 클래스로 정의해 두고 사용합니다.

@PropertySource 어노테이션에도 나와있지만 클래스패스 상의 datasource-db.properties 파일에 키=값 형태로 DB 접속정보를 정의해 두면 값을 주입받을것으로 기대하고 있습니다.
@Configuration
@PropertySource("classpath:META-INF/datasource-db.properties")
public class DatabaseInfoProperties {
    @Value("${erp.db.host}")
    private String host;

    @Value("${erp.db.port}")
    private String port;
   
    @Value("${erp.db.name}")
    private String dbName;

...


그럼 datasource-db.properties파일을 한 번 볼까요?

META-INF/datasource-db.properties 파일
erp.db.host=localhost
erp.db.port=1433



최종 원인 정리
DatabaseInfoProperties 클래스에는 @Value("${erp.db.name}")를 통해 erp.db.name이라는 properties 값을 주입받을것으로 기대했지만 정작 datasource-db.properties 파일에는 해당 값을 입력해두지 않았습니다. 따라서 DatabaseInfoProperties 클래스의 dbName 필드에는 값이 주입되지 않았을 것이고 이 값을 DataSource 빈을 생성하는데에 사용하는 DataSourceConfig 빈의 생성과정에서 예외가 발생한 것입니다.



해결 방법
첫번째로는 datasource-db.properties 파일에 해당 값을 입력해줍니다.
erp.db.host=localhost
erp.db.port=1433
erp.db.name=hellodb


두번째 방법으로는 DatabaseInfoProperties 클래스에 기본값을 설정해 두는 것입니다. @Value 부분을 보면 :@null 이 보입니다. :(콜론) 뒤에 기본값을 지정해두면 참조하고 있는 .properties 파일에 값이 입력되지 않았을때 기본으로 주입할 값을 설정해둘 수 있습니다. @null을 입력해 두었는데 null과 @null의 차이점은 문자열로 인식하느냐 정말 null값으로 인식하느냐의 차이입니다. null로 해두면 "null" 이라는 문자열이 기본값으로 주입되며, @null로 해둔경우 null값이 들어값니다. 혹은 기본으로 설정해두고 싶은 db명을 입력해 두어도 됩니다.
@Value("${erp.db.name:@null}")
private String dbName;

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

댓글을 달아 주세요! 질문 환영합니다!