반응형

Spring boot 를 학습하던 도중

 

AWS에 올리려다 git에 노출되면 안되는 값이 있어 외부 yml 파일을 만들고

 

application.yml 파일에 include 해서 data를 사용하려 했다.

 

그런데 데이터 주입이 되지 않았다.

 

myval:
	value: hi

이렇게 yml 파일이 설정 되어 있다고 가정 한다.

 

1. static 변수에 주입해서 사용했다

@Value("${myval.value}")
private static String val;

이런 식으로 사용 하였는데 데이터가 주입되지 않았다.

 

기존에 구현했던 클래스는 상수에 값을 때려 박고 그 값을 static 메소드에서 사용하도록 했었다.

 

그 점을 인지 못하고 그냥 변수 부분만 바꾸면 되겠지 하고 사용했지만, 실패!

 

2. static 키워드를 제거하고 new MyClass();와 같이 인스턴스 생성해서 사용했다.

 

@Component
@ConfigurationProperties(prefix="myval")
@Getter
@Setter
public class MyClass{
	private String value;
}

 

new MyClass(); 로 생성해서 value값을 출력하는 메소드를 만들고 호출해 봤지만

 

null 값이 나온다. 실패!

 

3. (2)번 처럼 만든 클래스를 @Autowired로 주입 시켜 사용했다.

public class TestMain{
	
    @Autowired
    private MyClass myclass;
    
    public void test(){
    	myclass.출력메소드();
    }
}

 

yml 파일의 데이터를 사용하는 클래스를 호출하는 곳에서 출력 메소드를 호출해 봤고 성공했다!

 

@Autowired, @Inject, @Resource, @Value 어노테이션들은 스프링의 BeanPostProcessor 구현체가 처리한다. 이는 (무엇이든간에) 자신만의 BeanPostProcessor나 BeanFactoryPostProcessor 타입내에서는 이러한 어노테이션들을 적용할 수 없다는 의미이다. 이러한 타입들은 반드시 명시적으로 XML이나 스프링의 @Bean 메서드를 사용해서 '연결해야' 한다.

 

구글링을 해서 찾아봤지만 위와같은 글만 있고 정확한 원인은 찾을 수 없었다..

 

혹시 왜 그런지 알고 계시면 답변 부탁드립니다~~!

 

그리고 yml 또는 properties 파일에서 값을 읽어오는 Class에는 setter 메소드가 꼭 있어야 한다.!!!!!!

 

--------------------------------------추가--------------------------------

좀 더 알아본 결과 Property 값 주입은 Bean 컨테이너 즉 ApplicationConetxt가 하는데, 서버가 올라가고 ServletContext가 Initialize 되면 onRefresh 메서드에 의해 Bean이 초기화 된다. 이 때 Bean을 스캐닝해서 의존이 있다면 의존을 주입한다. 이 과정에서 플레이스 홀더에 값을 채워주는 것이다!..

그렇기 때문에 임의로 new를 이용해 인스턴스를 생성하게 되면 값 주입이 이루어 지지 않는 것이다.

 

중요한 것은 @Autowired가 아니라 플레이스 홀더가 있는 클래스가 Bean이면서 동시에 context refresh에 의해 처리 되는가 아닌가의 차이이다.

자세한 것은 Spring.io에 Properties 관련 항목을 보면 나와있다.

반응형

+ Recent posts