스프링 책을 쓰면서 계속 피곤한 점은 항상 내용을 쉽고 평이하게 풀어서 설명하려고 노력해야 한다는 점이다. 그냥 어려운 용어가 가득한 복잡한 말로 한줄이면 될 것을 용어 설명까지 곁들여서 풀어쓰면 한 페이지가 되기도 한다.

그래서 가끔은 나의 지적인 욕구를 만족시켜줄만한 놀잇감을 찾게되는데, 제일 만만한게 역시 스프링이라 자주 하는 짓이 스프링 소스 연구이다. 한동안 좀 쉬었더니 그 사이에 많이 변한 것들이 보이고 해서 다시금 소스 분석을 시작하기로 했다.

기존에 그냥 소스 보면서 혼자 흥분하던 차원을 넘어서 두가지 정도 더 수고를 하기로 했는데, 하나는 블로그에 글을 남기는 것이고 하나는 분석한 소스의 구현 방법을 테스트 코드로 만들어서 일종의 학습테스트로 사용하는 것이다.

블로그는 뭐 어짜피 조금만 기술적인 내용을 올리면 다들 관심이 없는 듯 하니, 더더욱 어려운 얘기들이라  읽는 사람을 전혀 고려하지 않고 맘것 끄적여 볼테다. 타이틀은 InsideSpring. 스프링3 글을 쭉 쓰면서 번호를 달아서 쓰는데 나름 숫자 올라가는 것을 보는 재미가 쏠쏠하다. 이것도 그래야지.

 

첫번째로 어제 좀 뒤져본 소스는 이번에 3.0 M3에 새로 추가된 @Configuration, @Bean 등을 이용한 일명 annotated factory method이다. 이름은 factory method지만 사실은 JavaConfig이라고 하는게 더 이해하기 좋다. 행여나 단순한 factory method로 오해해서, 코드에 있는 대로 동작할 것이라고 생각하는 오해를 낫지 않을까 살짝 우려가 되는데, 탈은 자바코드지만 실제로는 그보다 심오하게 동작한다.

아래와 같이 생긴게 annotated factory method다. 빈으로 직접 쓰지는 않는 스트링을 용감하게 쓴 것은 새 빈 정의하기가 만들기가 귀찮아서. 아무튼 <bean id=”hello” class=”java.lang.String”>…</bean> 이것을 factory method로 정의한 것이다.

@Configuration
    static class Config {
        @Bean
        public String hello() {
            return "Hello";
        }
    }

Annotated factory method 자체를 SpringInside 분석할 이유는 없고.

내가 궁금했던 것은 이 것을 적용하는 방법이다. 그래서 4가지 정도의 @Configuration 적용방법을 찾아보았다.

 

XML

레퍼런스에 나오는 방법은 annotation-config을 정의해주고, 이 @Configuration이 있는 bean을 등록해주는 것이다. 즉 configuration class가 빈으로 잡히면 이를 보고 그 안에서 설정한 @Bean에 해당하는 bean을 등록해주는 것이다.

그래서 방법은annotation-config이 되도록 해주고 @Configuration 클래스를 빈으로 등록해주는 것이다. 이러면 XML에는 없는 hello라는 아이디를 가진 빈이 짜잔 등록된다. 해당 빈의 객체는 “Hello” 스트링 오브젝트이고.

    <context:annotation-config />

    <bean id="config" class="org.opensprout…Config">
    </bean>

테스트는

@Test public void atConfigurationWithXml() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("AnnotatedFactoryMethodTest.xml",
                The4OtherWaysToApplyAnnotatedFactoryMethodTest.class);
        String hello = ctx.getBean("hello", String.class);
        assertThat(hello, is("Hello"));
    }

 

또 한가지 방법은 annotation-config 대신에 bean scanner를 이용하는 것이다. 이럴땐 @Configuration 클래스의 빈 등록 자체도 필요없다. @Component처럼 자동 등록되면서 factory method에 의해서 빈 생성도 된다.

 

이게 사실 권장 방법인데 내가 해보고 싶은 것은 XML없이 자바코드로만 이걸 적용하는 것이다. 기껏 설정도 자바 클래스인데 저걸 위해서 또 XML을 쓴다는게 맘에 안들었고, 원래 JavaConfig프로젝트에서는 ApplicationContext를 만들면서 config클래스를 주어서 부트스트래핑할 수 있게 되어있는데, 스프링으로 와서는 그 개념이 없어졌다. 컥.

 

이제 동작원리를 파악해보자. 왜 annotation-config 설정을 하면 저게 먹는지도 살펴보자.

원래 XML에 없는 새로운 빈을 등록해주는 방법은 BeanFactoryPostProcessor를 쓰는 것이다. 이 놈은 bean factory가 만들어진 후에 한번 후처리를 해주는 건데, 주요 용도는 바로 이런 다이나믹한 빈의 등록이나 빈의 바꿔치기 등등에 사용한다. 이미 정의된 빈의 내용을 바꾸는 건 BeanPostProcessor가 담당한다. 이건 프로퍼티 세팅등의 용도에서 많이 쓴다. 이 두가지는 스프링의 고급 사용자라면 반드시 알고 있어야 할 것인데, 실제로 응용하는 사람을 본적은 없다. 오히려 스프링 스스로가 이것을 이용해서 계속 확장하고 있을 뿐이고. 애노테이션을 이용한 각종 설정도 결국 얘네들이 담당하는 것이다.

 

아무튼 이 @Configuration의 처리를 담당하는 것은 ConfigurationClassPostProcessor이다. 이것이 등록된 빈 중에서 @Configuration이 달린 놈을 찾아서, 그 안의 설정을 보고 추가적으로 빈을 등록해주는 빈 팩토리 후처리 작업을 해준다.

 

이제 위의 XML에서 하던 것을 자바코드로만 해보자. 빈 팩토리부터 시작한다.

BeanFactory

이건 원시적인 놈이라 실전에서는 잘 안쓰지만 그래도 스프링의 핵심중의 핵심 아닌가. BeanFactory의 구현 클래스를 따라가다 보면 DefaultListableBeanFactory가 나온다. 이게 나중에 AppContext에서도 내부적으로 정의해서 사용하는 놈이다. 이 클래스의 특징은 BeanFactory뿐만 아니라 BeanDefinitionRegistry 인터페이스도 구현해주는 것이다. 이 BeanDefinitionRegistry는 BeanDefinition 인터페이스를 구현한 객체로 빈의 정의 메타데이터를 넘기면 그것을 이용해서 bean을 짜잔 등록해주는 일을 하는 것이다. 모든 스프링의 빈은 결국 하나씩 이 BeanDefinition을 내부에 가지고 있다.

 

@Configuration을 적용한 Config클래스를 이 DefaultListableBeanFactory의 BeanDefinitionRegistry 인터페이스의 메소드를 이용해서 등록해준다. <bean id="config" class="org.opensprout…Config"> 이것과 마찬가지다. 여기까지 하면

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("config", new RootBeanDefinition(Config.class));

 

하지만 이건 단지 Config이라는 클래스를 빈으로 등록했을 뿐이다. 이걸로 hello라는 빈이 생성되지 않는다. 그걸 생성하려면 위에서 말한 ConfigurationClassPostProcessor를 이용해서 후처리를 해주는 것이다. AppContext와 달리 BeanFactory는 모든게 수동이다. 후처리도 직접 해주어야 한다.

먼저 후처리기를 등록하고

ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();

그리고 여기다 bean factory를 넘겨서 처리를 시킨다. 그럼 그 사이에 hello빈이 짜잔 등록.

pp.postProcessBeanFactory(factory);

이러면 준비완료.

이제 테스트 해보면 hello빈이 잘 나올 것이다.

String hello = factory.getBean("hello", String.class);
assertThat(hello, is("Hello"));

 

이게 @Configuration이 적용되서 빈이 생성되는 내부 구조이다.

여기서 궁금한 것은 그럼 왜 처음 XML을 이용한 방식에서는 이런 ConfigurationClassPostProcessor 가 등장하지 않느냐는 점이다. 대신 @Autowired, @Required등을 쓰기 위한 <context:annotation-config />만 정의했는데 ConfigurationClassPostProcessor 까지 어떻게 적용되었는가 하는 점이다.

 

이것이 궁금해서 스프링의 내부를 더 뒤져보았다.

길어지니 한번 쪼개서 써야겠다. 나머지 두가지 방법은 내일 적자.

Related posts:

  1. InsideSpring (1) Annotated Factory Method (@Configuration)을 쓰는 4가지 방법 (3)
  2. InsideSpring (1) Annotated Factory Method (@Configuration)을 쓰는 4가지 방법 (2)
  3. InsideSpring (3) 스프링 밖에서 WebApplicationContext에 접근하기
  4. 테스트 할 수 없는 것을 테스트 하기. Spring ROO와 static method mocking.
  5. InsideSpring (4) 빈 스캐너는 클래스를 로딩할까?
  6. InsideSpring (2) AutoProxyCreator는 Pointcut의 ClassFilter만 사용하지 않는다
  7. S1A 2008 셋째날 – Spring JavaConfig
  8. Spring 3.0 (39) Spring 3.0 M3 공개
  9. Spring 3.0 (33) JavaConfig의 통합과 변신. 메타-빈(meta-bean) 개념의 등장.
  10. Spring 3.0 (56) @Bean 사용의 주의사항
  11. Inside Spring (5) PropertyPlaceholderConfigurer를 @Bean으로 정의해서는 안되는 이유
  12. Spring 3.0 (54) 드디어 등장한 ConfigurationClassApplicationContext
  13. Spring 2.0의 XML확장기능 (1)
  14. 스프링 빈의 이름은 한글로 지어도 된다
  15. Spring 3.0 (58) Static Class를 XML없이 빈으로 등록하기

Facebook comments:

to “InsideSpring (1) Annotated Factory Method (@Configuration)을 쓰는 4가지 방법 (1)”

  1. 토비님 글을 보니 ‘아~ 그래서 그렇구나!’ 라는 생각이 계속 떠오르네요. 즐겁네요.^^

  2. 조금만 기술적인 내용이면 어려워서 못읽는 나에게도 읽는 재미가 쏠쏠하게 쓰셨네요. ConfigurationClassPostProcessor이 왜 XML 방식에는 등장하지 않는지 다음 포스트가 기대됩니다. ^^*

  3. Hop Over To THIS WebSite

  4. I agree with your thought.Thank you for your sharing.

  5. thank you for share!

  6. thank you for share!

  7. thanks for share!

  8. thanks for share!

  9. Click For More Info
    [url=http://www.zaxw.org/engs/michael-korskentona5g.html]michael kors madrid[/url]
    michael kors madrid

  10. You can check here
    [url=http://www.pyfilm.cn/member/uploadsiselect.php?/miu-miu-addict-is-the-nice-choice-for-the-season-2013.html]miu miu addict-Is the nice choice for the season 2013[/url]
    miu miu addict-Is the nice choice for the season 2013

  11. Click For More
    [url=http://allr-med.com/manage/load.php?/manolo-blahnik-sizes-purchase-high-quality.html]manolo blahnik sizes-Purchase high quality[/url]
    manolo blahnik sizes-Purchase high quality

  12. thank you for share!

  13. Click To Find Out More
    [url=http://baileybuttontriplett.com]ugg triplet bailey button[/url]
    ugg triplet bailey button

  14. mbt shoes women InsideSpring (1) Annotated Factory Method (@Configuration)을 쓰는 4가지 방법 (1) » 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