기존에 구현했던 클래스는 상수에 값을 때려 박고 그 값을 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에 의해 처리 되는가 아닌가의 차이이다.