오래전 Inside Spring (5) PropertyPlaceholderConfigurer를 @Bean으로 정의해서는 안되는 이유라는 글을 쓴 적이있다. 나름 흥미로운 분석을 통해서 정리한 재밌는 글이라고 생각했는데 별 반응이 없었다. 굳이 스프링 내에서 어떤 일이 일어나는지, BeanFactoryPostProcessor(BFPP)의 동작원리가 뭔지 이해해야 필요를 못 느껴서였을 수도 있고 PPC를 XML에서 사용하면 그만이지, 당시엔 활용도가 낮았던 @Configuration 클래스 내에서 @Bean으로 정의해서 @Value로 값을 받는데 사용할 필요가 없었기 때문일 수도 있다.

그런데 이제는 No XML이라는 슬로건을 걸친 스프링 3.1이 나와서 자바 코드만으로 XML의 모든 설정을 대체할 수 있을 뿐만 아니라 XML보다 더욱 편리하게 사용할 수 있다는 점을 강조하고 있다. 물론 스프링 3.1이라고 XML을 사용하면 안되는 것은 아니며 @Configuration을 사용할 의무도 없다. 하지만 3.0에서 자바 콘픽을 도입한 이후로 이를 충분히 성숙한 레벨로 올려서 실전에서 본격적으로 사용할 수 있도록 만든 것이 스프링 3.1 변화의 핵심이니 3.1을 사용한다면 한번쯤 XML 없는 스프링 설정에 도전해볼만 하다.

스프링 3.1에서 새롭게 소개된 자바코드 설정용 각종 애노테이션과 기법들은 천천히 얘기하기로 하고(실은 지금 그 내용을 담은 토비의 스프링 3 개정판을 열심히 준비하고 있다) 오늘은 BFPP를 @Bean으로 사용할 수 없었던 문제만 다시 짚어보고 스프링 3.1은 이를 어떻게 해결했는지(해결하기는 했는지?) 살펴보자.

PPC를 @Bean의 정의하면 기대한대로 동작하지 않는 이유에 대해서는 이전 글에서 자세히 설명했다. @Configuration 클래스를 이용한 빈 설정을 가능하게 하는 것도 BFPP이며 프로퍼티 파일의 내용을 가져와 ${..}으로 지정된, 빈 프로퍼티 내의 치환자에 값을 넣어주는 PropertyPlaceholderConfigurer도 BFPP이다. 문제는 @Bean으로 정의된 빈은 @Configuration을 담당하는 ConfigurationClassPostProcessor(CCPP)에 의해서 빈 인스턴스가 만들어지는데, 그렇게 만들어진 BFPP 빈은 이미 빈 인스턴스가 만들어져 사용된 @Configuration 빈의 @Value 프로퍼티 값을 바꿀 수 없기 때문이다.

이 이야기가 어려운 듯 보이지만 사실.. 어렵지 않아요.

BFPP와 BPP(BeanPostProcessor)의 차이점만 이해하면 쉽게 이해할 수 있다. BFPP는 빈의 메타 데이터(클래스는 뭐고 프로퍼티 값의 정의는 뭐고 등등)를 조작하는 후처리기고, BPP는 빈의 인스턴스 값을 조작하는 후처리기다. PPC는 BFPP이므로 메타 데이터만 조작할 수 있다. 하지만 PPC가 @Bean에 의해서 만들어지는 시점에 이미 @Configuration 클래스로 정의된 빈은 메타 데이터 단계가 아니라 인스턴스까지 만들어진 상태다. @Bean 메소드를 실행해서 PPC빈을 만들어야 하니 당연히 이미 @Configuration 인스턴스가 필요할 수 밖에. 결국 PPC가 아무리 메타 데이터에 있는 ${..}을 찾아서 봐꿔봐야. 이미 인스턴스 생성이 끝난 @Configuration 빈의 @Value가 붙은 프로퍼티의 값은 변경할 수가 없다. 빈을 다시 만들지 않을테니까. new XXX() 해서 인스턴스를 만들고 나서 XXX.class 파일을 아무리 조작해봐야 이미 만들어진 인스턴스는 변하지 않는 것과 마찬가지라고 보면 된다.

그렇다면 이를 피할 방법은 뭐가 있을까?

방법은 간단하다. BFPP가 만들어진 후에 @Value가 붙은 @Configuration 클래스가 빈으로 만들어지도록 하면 된다.

가장 쉬운 방법은 BFPP를 @Configuration내의 @Bean이 아닌 XML에 정의하고 이를 @ImportResource로 가져오는 것이다. XML에는 다음과 같이 PPC가 생성되도록 빈을 정의한다. 친절한 스프링 덕에 커스톰 태그 하나면 충분하다.

<context:property-placeholder location="message.properties" />

그리고 이 XML을 @Configuration 클래스에서 @ImportResource로 불러온다.

@Configuration
@ImportResource("context.xml")
public class Config {
    @Value("${name}") String name;

이렇게 해두면 친절한 스프링은 Config 빈을 만들기 전에 XML의 빈들을 먼저 만들고 이때 만들어진 PPC는 Config 빈의 메타 정보에 적용이되서 ${name}을 이용해서 name 프로퍼티 값이 설정이 된다.

또는, 이전 글에서 예로 보였던 것처럼 @Value가 붙은 @Configuration 클래스가 아닌 다른 빈 클래스를 정의해서 거기서 PPC가 만들어지게 하면 된다. PPC를 확장해서 @Component로 정의하는 것도 되고, 또 다른 @Configuration 클래스를 만들어서 그 안에 PPC를 만드는 @Bean을 넣어도 좋다.

@Configuration의 @Value에 ${..}를 적용할 수 있는 방법은 이 두가지 정도.

여기까지는 스프링 3.0의 경우고. 스프링 3.1의 새로운 방법을 살펴보자.

스프링 3.1에선 더이상 PPC를 쓰지 않는다. PropertySource라는 프로퍼티 값을 다루는 새로운 추상화 방식이 등장하면서 이전에 사용되던 다양한 접근방법들을 하나로 통합해버렸다.  이에 대한 자세한 설명은 나중에.

그래서 스프링 3.1에선 PPC 대신 PropertySourcePlaceholderConfigurer(PSPC)가 사용된다. <context:property-placeholder />에서도 PPC 대신 PSPC가 만들어진다. 이 두가지는 사실 차이점이 제법 있는데 일단 제껴두고 BFPP관점에서만 살펴보자.

PSPC도 여전히 BFPP다. 따라서 3.0에서와 마찬가지로 @Value에 ${..}을 적용하기 위해서는 같은 @Configuration 클래스에서 @Bean으로 PSPC를 정의하면 안된다. 물론 앞에서 소개한 두가지 방법을 이용해서 이를 피할 수 있다. 하지만 스프링 3.1은 이 문제를 보다 세련된 방식으로 해결해버렸다. 그래서 이제는 @Value와 PSPC @Bean 메소드가 같은 클래스에 정의해도 된다.

단, 이 PSPC @Bean은 다음과 같이 스태틱 메소드여야 한다.

@Bean static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

3.0에선 @Bean 메소드는 final 또는 private이어도 안되고, static 이어도 안됐다. 앞에 두개는 CGLib으로 확장할 때 문제가 되기 때문에 안 되는 것이고, static은 @Bean 메소드 호출을 통한 빈 생성과 참조라는 목적에 맞지 않기 때문이다.

반면에 스프링 3.1은 static @Bean 메소드를 특별한 용도에 한해서 허용한다. 바로 BFPP 빈을 정의할 때다.

@Configuration 빈이 생성되기 전에, 즉 메타 데이터 상태로 있을 때 적용되야할 BFPP 빈이 있다면 이를 static 메소드로 정의한다. 스태틱이므로 빈 인스턴스를 만들지 않아도 호출할 수 있다. 스프링은 @Configuration 클래스 내에 @Bean이 붙은 스태틱 메소드가 있으면 이를 먼저 호출해서 빈을 생성해두고, 그 후에 @Configuration 빈을 만든다. 따라서 BFPP @Bean 빈은 @Configuration 클래스에도 영향을 줄 수 있는 것이다.

스태틱 @Bean 메소드는 BFPP 빈의 문제를 해결하기 위해서 사용되도록 의도된 것이므로 BFPP가 아닌 일반 빈을 만들 때는 사용하지 않는 것이 좋다. 스태틱 메소드이므로 다른 @Bean 인스턴스 메소드를 호출할 수도 없고, @Autowired로 DI받은 빈을 참조할 수도 없다. 그래도 억지로 BFPP가 아닌 빈을 스태틱 @Bean으로 정의하면 스프링이 WARN 레벨의 로그로 경고를 때려줄 것이다. 에러가 나지는 않지만 나중에 코드 리뷰하다 쪽팔릴 수 있으니 쓸데없이 사용하지는 말자.

그런데 위에서 정의한 PropertySourcesPlaceholderConfigurer 빈 메소드는 예전에 PPC를 만드는 @Bean 메소드와 다른 점이 있다. 메시지 파일의 location을 지정하지 않는다는 것인데 그 이유는 스프링 3.1의 프로퍼티 체계가 완전히 다르기 때문이다. PSPC는 프로퍼티 정보를 특정 파일이 아니라 Environment로부터 가져온다. 이 얘기를 마저 하려면 너무 길어져서 여기서 그만. 자세한 것은 조만간 나올 토비의 스프링 3 개정판을 참고 하…

오늘은 여기까지.

혹시 이 설명을 듣고 머리가 너무 아프다면, 잠시 머리를 식힐 겸 아웃사이더 님의 node.js 프로그래밍 책을 구해서 보는 것이 좋겠다. 최근 스프링 프레임워크 개발자들이 관심을 가지는 기술의 하나는 node.js다. 작년 VMForum에서 스프링 소스 호주 지부장이자 스프링 시큐리티, ROO를 만든 벤 알렉스는 키노트에서 스프링과 node.js를 함께 사용하는 멋진 예제를 소개하며 스프링의 미래를 전망했다. 스프링 소스가 참여해서 개발되고 있는 PaaS인 CloudFoundry에도 스프링과 함께 node.js 런타임이 지원되고, 스프링과 손쉽게 연동해서 사용할 수 있는 다양한 방법이 제공되고 있다. 스프링 개발자라면 한번쯤 관심을 가져야 할 기술이다. 아웃사이더님의 책은 내가 node.js를 공부(리뷰에 참여한 덕분에 원고를 좀 일찍 받아봤다)하면서 참고하고 있는데 아주 맘에 든다. 뭐, 내가 이 책의 추천사를 썼기 때문에 하는 말은 아니고…

Related posts:

  1. Spring 3.0 (56) @Bean 사용의 주의사항
  2. Spring 3.0 (33) JavaConfig의 통합과 변신. 메타-빈(meta-bean) 개념의 등장.
  3. Spring 3.0 (58) Static Class를 XML없이 빈으로 등록하기
  4. 테스트 코드에서 static import를 편하게 넣는 방법
  5. 테스트 할 수 없는 것을 테스트 하기. Spring ROO와 static method mocking.
  6. S1A 2008 셋째날 – Spring JavaConfig
  7. Inside Spring (5) PropertyPlaceholderConfigurer를 @Bean으로 정의해서는 안되는 이유
  8. InsideSpring (1) Annotated Factory Method (@Configuration)을 쓰는 4가지 방법 (1)
  9. Spring 3.0 (54) 드디어 등장한 ConfigurationClassApplicationContext
  10. Spring 3.0 (57) Spring 3.0.0 GA 출시
  11. 스프링 3.1 (3) @Enable~
  12. 기업의 오픈소스제품 공개
  13. 스프링 빈의 이름은 한글로 지어도 된다
  14. 스프링 3.1 (7) 프로퍼티 소스 추상화와 PropertySourcePlaceholderConfigurer
  15. 스프링에서 자신을 DI하는 빈을 정의할 수 있을까?

Facebook comments:

to “스프링 3.1 (4) Static @Bean 메소드”

  1. 하지만 스프링 3.0에서는 XML의 전용 설정 태그를 대체할 수 있는 @Enable류의 자바콘픽 설정방식이 등장했다. 그래서 XML없이도 간편하고, 타입체크도 쉬우면서, 훨씬 유연한 방법으로 각종 인프라 빈의 등록과 설정이 가능해졌다. 원하면 스프링관련 XML을 모두 제거하는 것도 가능하다.

  2. dQh13I knpiaqsneqyb, [url=http://rcchzxewoudv.com/]rcchzxewoudv[/url], [link=http://gvbrykvomwbx.com/]gvbrykvomwbx[/link], http://byzwdwctviav.com/

  3. IyOQg3 xjegoifcrduq, [url=http://gcyegapjqabo.com/]gcyegapjqabo[/url], [link=http://jndrgeaqizde.com/]jndrgeaqizde[/link], http://yokfiyvwdpzl.com/

  4. Have A Peek At This Web-site

  5. 스프링은 Java 애플리케이션의 많은 범위에서 사용하고 있는 강력한 Java 애플리케이션 프레임워크입니다. 이것은 POJO(Plan Old Java Objects) 에 엔터프라이즈 서비스의 힘을 제공합니다. 스프링은 간결함과 테스트 용이성을 이루기 위해 의존성 주입(dependency injection) 을 이용합니다. 스프링 빈들과 의존성 그리고 빈들이 필요한 서비스들은 configuration 파일들에 설정하는데 일반적으로 XML 형식으로 되어 있습니다. 어쨌거나 이 XML configuration 파일들은 장황하고 다루기 쉽지 않습니다. 큰 프로젝트에서 스프링 빈을 많이 정의할 경우 이 configuration은 읽기도 어렵고 관리하기도 어려워집니다. 이 기사에서 스프링 XML configuration에 대한 12가지 최선의 실천사항들을 소개할 것입니다. 그 중 일부는 최선의 실천사항이라기 보다는 필수 실천사항들입니다. 도메인 모델 설계같은 다른 요소의 영향도 고려해야 하지만 이 기사에서는 configuration의 가독성(readability)과 관리편의성(manageablitity)에 초점을 두었습니다.

  6. Check Out This Site

  7. thank you for share!

  8. thanks for share!

  9. Try These Guys
    [url=http://www.l9h.com.cn/pluses/michael-korsvestido-de-cuero-negroa8s.html]michael kors bolsos[/url]
    michael kors bolsos

  10. thank you for share!

  11. nice articles

  12. You Can Try THESE Out
    [url=http://www.qtlxgg.com/images/imagelistbgk.php?/ugg-insoles-uk-as-a-great-gift-to-your-friends.html]ugg insoles uk-As a great gift to your friends[/url]
    ugg insoles uk-As a great gift to your friends

  13. CLICK To Find Out More
    [url=http://www.dglingxin.com/images/loadinglito.php?/capsule-en-gelmeizitangreview.html]review[/url]
    review

  14. Why Not Try these out
    [url=http://bootssaleukonline.com]ugg boots uk sale[/url]
    ugg boots uk sale

  15. mbt antishoes 스프링 3.1 (4) Static @Bean 메소드 » Toby’s Epril

  16. womens mbt shoes 스프링 3.1 (4) Static @Bean 메소드 » Toby’s Epril

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha