티스토리 툴바

Spring의 XML 파일 중심의 설정 방식은 중앙집중적이다. 이에 반해 JPA(Java Persistence API)처럼 애노테이션(Annotation)을 사용하여 메타 정보를 설정하는 방식은 분산형이라 할 수 있다. 양자택일의 형태로 둘 중의 하나만을 사용하면 팀 작업의 경우 혼선을 줄일 수 있을지 모른다. 하지만, 보다 실용적인 방법은 어디에 기록하는 것이 관리(변경)하기 용이하고 이해가 편한지 고려해보는 것이다.

CarPlant not accepting null CarModels@Required@NotNull 애노테이션을 보면 분산형 설정(decentralized configuration)이 유용한 사례로 바로 감이 온다. 더구나 JPA의 애노테이션에 익숙하면 편안함(?)마저 느낄지 모른다.

Spring 2.0에서는 @Required을 활용해서 프로퍼티 설정을 강제할 수 있다. 강제한다는 말은 프로퍼티 설정 없이 인스턴스를 얻으려고 하면 예외를 발생시킨다는 것이다. 가장 보편적 쓰임은 ApplicationContext를 쓸 때이다.

  try{
   BeanFactory factory = new FileSystemXmlApplicationContext(".../applicationContext.xml");
   fail("A BeanCreationException expected.");
  }catch (BeanCreationException e) { } // success

사용자 코드에서 (프로그래밍적으로는) 할 일은 없다. 설정 파일에서 RequiredAnnotationBeanPostProcessor만 정의해주면 된다.

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

ApplicationContext가 BeanPostProcessor를 자동으로 인식해서 등록해주기 때문이다.

BeanFactory 구현을 사용해야 할 경우 역시 RequiredAnnotationBeanPostProcessor를 등록해주면 되는데, 약간의 코드 작성이 요구된다.

  XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource(".../applicationContext.xml"));
  factory .addBeanPostProcessor(new RequiredAnnotationBeanPostProcessor());
  try{
   assertNotNull(((BeanFactory)factory ).getBean("foo"));
   fail("A BeanCreationException expected.");
  }catch (BeanCreationException e)  { } // success

프로그래밍적인 등록이 있었기 때문에 설정 파일 수정이 필요하지는 않다.

애노테이션이 지원되지 않았던 Spring 1.x에서도 이러한 작업은 가능하다. ApplicationContext를 사용하는 경우라면 코드는 2.0의 경우와 같다. 별도의 코드가 요구되지는 않는다. 설정 파일에서 RequiredAnnotationBeanPostProcessor를 설정하는 대신에 해당 빈 설정에서 dependency-check 속성값을

<bean id="bar" class="ioc.autowire.Foo" dependency-check="all" />

bar가 문제를 일으킨 것인지 분명히 하기 위해 다음과 같이 테스트를 해볼 수 있다.

  try{
   BeanFactory factory = new FileSystemXmlApplicationContext("t.../applicationContext.xml");
   fail("A BeanCreationException expected.");
  }catch (BeanCreationException e) {
   assertEquals("bar", e.getBeanName());
  }

인스턴스를 미리 생성하지 않는 BeanFactory 구현체를 쓸 경우라면 getBean()을 호출하는 시점에서 확인할 수 있다.

  try{
   factory = new XmlBeanFactory(new FileSystemResource(".../applicationContext.xml"));
   factory.getBean("bar");
   fail("A BeanCreationException expected.");
  }catch (BeanCreationException e) {
   assertEquals("bar", e.getBeanName());
  }

dependency-check의 값은 default, none, all, simple, object 등이 있다. 위에서 Foo 타입의 객체가 기본형(primitive)이나 컬렉션 타입의 프로퍼티를 갖는 경우 simple을 사용할 수 있고, 사용자 정의 타입(일반 빈)을 프로퍼티로 갖는다면 object를 사용한다. 둘을 모두 갖고 있다면 all을 쓴다. defaultnone과 같은데 이는 dependency-check를 정의하지 않는 것과 결과가 같다.

설정

트랙백

댓글