Whiteship's Note


Using Java Configuration



원문 : Chapter 7. Using Java Configuration

애플리케이션에서 애노테이션을 설정 파일로 사용할 수 있는 방법으로 다음과 같은 클래스가 있다.

    * AnnotationApplicationContext     

이 클래스는 Ant 스타일 패턴을 사용하여 애노테이션을 사용한 설정 클래스 이름을 받을 수 있다.

      ApplicationContext oneConfig =
             new AnnotationApplicationContext(SimpleConfiguration.class.getName());
      ApplicationContext aBunchOfConfigs =
             new AnnotationApplicationContext("**/configuration/*Configuration.class");

이 애플리케이션 컨텍스트는 주어진 패턴에 매칭되는 클래스 패스 내의 클래스들을 자동으로 읽어들이고 빈으로 등록한다. 이 방법의 단점은 설정 객체를 parameterization 할 수 없다는 것이다.

    * Configuration post processor

      <beans>
       <!-- Spring configuration -->
       <bean class="org.springframework.samples.petclinic.JdbcConfiguration"/>

       <!-- Java Configuration post processor -->
       <bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>
      </beans>

두 번째 방법은 설정 처리 뿐만 아리나 (ConfigurationPostProcessor를 통해서) 설정 객체 자체도 제어 하기 때문에 보다 많은 설정 옵셥을 제공한다.

설정을 빈으로 정의함으로써, Spring 컨테이너는 설정을 (속성 또는 특정 생성자를 사용해서)설정할 수 있다.

      <beans>

       <!-- a possible configurable configuration -->
       <bean class="org.my.company.config.AppConfiguration">
          <property name="env" value="TESTING"/>
          <property name="monitoring" value="true"/>
          <property name="certificates" value="classpath:/META-INF/config/MyCompany.certs"/>
       </bean>

       <!-- Java Configuration post processor -->
       <bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>

      </beans>

'Spring JavaConfig > Chapter 7' 카테고리의 다른 글

Using Java Configuration  (0) 2007.07.25
top

Write a comment.


Mixing XML and annotations



원문 : Chapter 6. Mixing XML and annotations

Java 설정과 XML 설정은 상호 베타적이지 않다. 하나의 Spring 애플리케이션에서 모두 사용될 수 있다. XML 파일에 있는 bean을 가져오기 위해서는, Spring 컨테이너를 사용해야 한다. 이전에 언급했다시피, @ExternalBean 애노테이션(추천하는 방식)을 사용하여 그렇게 할 수 있다. 이렇게 하고 싶지 않거나 이런 방법이 부적절한 경우네는, @Configuration 클래스에의해 사용되는 beanFacotry에 접근할 수 있다. 이렇게 하려면, 설정 클래스가 ConfigurationSupport 를 상속하거나 BeanFacrtoryAware 인터페이스를 구현하도록 하면 된다.

다음의 XML 설정을 살펴보자.

<bean id="myBean" class="MyBean"/>

myBean을 Java에서 참조하려면 다음과 같이 작성할 수 있다.

@Configuration
public class MyConfig extends ConfigurationSupport {

  @Bean
  public ExampleBean anotherBean() {
     ExampleBean bean = new ExampleBean("anotherBean");
     bean.setDep(getBean("myBean")); // use utility method to get a hold of 'myBean'
     return bean;
  }
}

@Configuration
public class MyOtherConfig implements BeanFactoryAware {
  private BeanFactory beanFactory;

  public void setBeanFactory(BeanFactory beanFactory) {
     // get access to the owning bean factory
     this.beanFactory = beanFactory;
  }

  @Bean
  public ExampleBean yetAnotherBean() {
     ExampleBean bean = new ExampleBean("yetAnotherBean");
     bean.setDep(beanFactory.getBean("myBean")); // use dependency lookup
     return bean;
  }
}

다시 한 번 강조하지만, ConfigurationSupport나 BeanFacrtoryAware를 사용하기 전에 똑같은 기능을 제공하는 (offers the same capability in a refactoring friendly manner) @ExternalBean을 사용하고 싶지는 않은지 재고하기 바란다.

JavaConfig 배포판에 변경된 Petclinic 예제에 보면 몇몇 XML 설정 부분을 Java와 Groovy로 교체한 것이 있다. 샘플 폴더를 살펴보길 바란다.

'Spring JavaConfig > Chapter 6' 카테고리의 다른 글

Mixing XML and annotations  (0) 2007.07.24
top

Write a comment.


Naming strategy



원문 : Chapter 5. Naming strategy

지금까지의 모든 예제들은, 메소드 이름으로 메소드를 호출하여 bean을 받아왔다.

@Configuration
public class ColoursConfiguration {
  // create a bean with name 'blue'
  @Bean
  public Color blue() {
    ...
  }
  ...
}

// dependency lookup for the blue colour
applicationContext.getBean("blue");

몇몇 경우에는, 이러한 네이밍 스키마가 적합하지 않을 수도 있다. 즉 서로 다른 설정 클래스에서 같은 이름의 정의를 사용하고 있는 경우가 그렇다. 이러한 네이밍 지침을 사용하는 입장에서 맘대로 변경할 수 있도록 BeanNamingStrategy 인터페이스를 제공하고 있다.

물론, 코드를 작성하기 전에, Spring이 기본으로 제공하고 있는 MethodNameStrategy 구현체들을 살펴보는 것이 좋겠다.

 <!-- Java Configuration post processor -->
 <bean class="org.springframework.config.java.process.ConfigurationPostProcessor">
    <property name="namingStrategy">
       <bean class="org.springframework.config.java.naming.MethodNameStrategy">
          <property name="prefix" value="CLASS"/>
       </bean>
    </property>
 </bean>

이런 설정을 해두면, bean을 생성할 때 메소드 이름에 클래스 이름까지 붙여주게 된다.

// 새로운 작명 지침을 사용하여 blue 빈 가져오기
applicationContext.getBean("ColoursConfiguration.blue");

'Spring JavaConfig > Chapter 5' 카테고리의 다른 글

Naming strategy  (0) 2007.07.24
top

Write a comment.


Wire dependencies



원문 : Chapter 4. Wire dependencies

bean을 묶기 위해서, 간단하게 Java의 문법을 사용할 수 있다.

@Bean(scope = DefaultScopes.SINGLETON)
public Person rod() {
  return new Person("Rod Johnson");
}

@Bean(scope = DefaultScopes.PROTOTYPE)
public Book book() {
  Book book = new Book("Expert One-on-One J2EE Design and Development");
  book.setAuthor(rod());  // rod() method is actually a bean reference !
  return book;
}

위의 예제에서, 책의 저자는 rod 메소드의 반환값을 사용하고 있다. 하지만, book과 rod 모두 @Bean으로 마크된 메소드기 때문에, Spring의 관리하는 bean들을 반환하게 되며, 따라서 컨테이너의 관리 대상이 된다. rod 빈은 싱글톤이고 book 빈은 프로토타입이다. 설정 파일을 만들 때, Spring은 애노테이션 문맥을 알아차리고 rod() 메소드 호출을 'rod'라는 빈 name으로 참조하도록 한다.

이 컨테이너는 매번 book 빈을 요청할 때 마다 똑같은(싱글톤) rod 빈을 참조하고 있는 다른(프로토타입) book 빈을 반환할 것이다.

위의 코드는 아래와 동일하다:

<bean id="rod" class="Person" scope="singleton">
   <constructor-arg>Rod Johnson</constructor-arg>
</bean>

<bean id="book" class="Book" scope="prototype">
   <constructor-arg>Expert One-on-One J2EE Design and Development</constructor-arg>
   <property name="author" ref="rod"/>
</bean>

위의 예제는 가장 흔히 사용하는 scope을 사용하고 있지만, 어떤 타입의 scope이라도 사용할 수 있음을 알아두자.

@Bean (scope = "customer")
public Bag shopingBag() {
  return new Basket();
}

@Bean (scope = "shift")
public Manager shopManager() {
  ...
}

'Spring JavaConfig > Chapter 4' 카테고리의 다른 글

Wire dependencies  (0) 2007.07.24
top

Write a comment.


Bean Visibility



원문 : Chapter 3. Bean Visibility

JavaConfig의 멋진 기능 중 하나는 bean의 가시성을 설정할 수 있다는 것이다. JavaConfig는 메소드 접근 지시자를 사용하여 메소드에서 반환할 bean에 접근 할 수 있는지 없는지 여부를 결정할 수 있다.

다음의 설정을 살펴보자.

@Configuration
public abstract class VisibilityConfiguration {

  @Bean
  public Bean publicBean() {
     Bean bean = new Bean();
     bean.setDependency(hiddenBean());
     return bean;
  }
 
  @Bean
  protected HiddenBean hiddenBean() {
     return new Bean("protected bean");
  }

  @Bean
  private HiddenBean secretBean() {
     Bean bean = new Bean("private bean");
     // hidden beans can access beans defined in the 'owning' context
     bean.setDependency(outsideBean());
  }

  @ExternalBean
  public abstract Bean outsideBean()
}

위 설정 내용을 바탕으로 다음과 같은 XML 설정 파일을 사용할 수 있다.(여러 설정 파일 종류를 혼용하는 전략에 대해서는 본 챕터에서 다룰 것이다.)

<beans>
 <!-- the configuration above -->
 <bean class="my.java.config.VisibilityConfiguration"/>

 <!-- Java Configuration post processor -->
 <bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>

 <bean id="mainBean" class="my.company.Bean">
    <!-- this will work -->
    <property name="dependency" ref="publicBean"/>
    <!-- this will *not* work -->
    <property name="anotherDependency" ref="hiddenBean"/>
 </bean>
</beans>

위의 설정에서 하나의 JavaConfig가 설정에 포함되며, 3개의 빈을 생성할 책임을 지고 있다. publicBean, hiddenBean 그리고 secretBean이다. 이 세개의 bean들은 각자 서로를 참조할 수는 있지만, ApplicationContext 입장에서는 오직 publicBean만 참조할 수 있다. hiddenBean과 secretBean은 접근이 오직 VisiblilityConfiguration 내부로 제한되어 있다.

@Bean 애노테이션이 달리 메소드 중에 public이 아닌 것(protected, private, defalut)들은 모두 '감춰진' bean으로 생성될 것이다.

위의 예제에서, mainBean은 publicBean과 heddenBean을 사용하여 설정하고 있다. 하지만, hiddenBean은 숨겨져 있기 때문에 런타임시에 다음과 같은 에러를 발생시킨다.

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'hiddenBean' is defined
 ...

가시성을 제공하기 위해, JavaConfig는 Spring 컨테이너가 제공하는 application context 상속구조의 장점을 받아들였다. 자식 애플리케이션 컨테이너에서 숨겨진 빈들을 소유하고있는  부모 컨텍스트에 있는 빈들에 접근할 수 있다.

'Spring JavaConfig > Chapter 3' 카테고리의 다른 글

Bean Visibility  (0) 2007.07.24
top

Write a comment.


Components



원문 : Chapter 2. Components

애노테이션을 사용하여 자바 구조를 계층화 하는 자바 설정은, 개발자들이 자바만을 사용하여 빈을 생성하고 설정할 수 있도록 한다. 간단하게, 개발자는 자바 코드를 사용하여 빈을 만들고 설정하며, 컨테이너가 그것들을 사용하도록 지시한다. 계속 진행하기 전에, Spring의 이상은 설정파일이 어떤 형태든(자바든 XML이든) 상관없이 우지 된다는 것을 유념하라.

JavaConfig에서 사용할 수 있는 가장 중요한 애노테이션들을 살펴보자:

2.1. @Configuration

@Configuration 애노테이션은 설정 클래스를 지칭한다:

@Configuration
public class WebConfiguration {
   // bean definitions follow
}

@Configuration은 클레스에 적용하는 애노테이션이고 설정할 bean들에 기본으로 적용할 것들을 나타낸다.

@Configuration(defaultAutowire = Autowire.BY_TYPE, defaultLazy = Lazy.FALSE)
public class DataSourceConfiguration
     extends ConfigurationSupport {
}

<beans/> 태그와 동일하게 생각하면 된다. @Configuration 애노테이션을 달고 있는 클레스는 유틸리티 메소드를 제공하는 ConfigurationSupport 를 확장함을 나타낸다.

2.2. @Bean


이름이 암시하듯이, @Bean 애노테이션은 bean 정의(<bean/> 태그)를 나타낸다. 간단한 예제로 살펴보자.

@Bean (scope = DefaultScopes.SESSION)
public ExampleBean exampleBean() {
  return new ExampleBean();
}

위의 코드는 Spring 컨테이너에게 method의 이름(bean name)을 사용하여 bean을 생성하도록 하고, 값(실제 bean 객체)을 반환한다. bean은 session 스콥이다. 즉, exampleBean() 메소드는 HTTP session 마다 새로운 객체를 생성해 줄 것이다.

순수 자바 코드를 사용하기 때문에:

- static method를 사용하면 factory-mathod를 사용할 필요가 없다.

@Bean
public ExampleBean exampleBean() {
  return ExampleFactory.createBean();
}

또한

- 복잡한 객체 생성시 필요한 FactoryBean/MethodInvokingFactoryBean도 필요없다.

@Bean(aliases = { "anniversaries" })
public List<Date> birthdays() {
  List<Date> dates = new ArrayList<Date>();
  Calendar calendar = Calendar.getInstance();

  calendar.set(1977, 05, 28);
  dates.add(calendar.getTime());
  dates.add(computeMotherInLawBirthday());

  return dates;
}

@Bean은 메소드에 붙일 수 있는 애노테이션이고 bean 객체를 생성하고 설정할 때 사용할 자바 코드를 나타낸다. 이 애노테이션은 XML 빈 설정에서 사용할 수 있는 autowiring, lazy-init, dependecy-check, depends-onscope과 같은 대부분의 설정을 지원한다. 또한, 라이프사이클 메소드와 XXXAware 인터페이스도 전부 지원한다.

public class AwareBean implements BeanFactoryAware {

  private BeanFactory factory;

  // BeanFactoryAware setter
  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
   this.factory = beanFactory;
  }

  public void close(){
    // do clean-up
  }
}

@Bean(destroyMethodName = "close", lazy = Lazy.TRUE)
public AwareBean createBeanFactoryAwareBean() {
   return new AwareBean();
}

destroyMethodNanme 외에도, @Bean 애노테이션은 initMethodName을 제공한다. though its usage is discourage as one already has control over the object creation and thus can call the initializing method if needed.

2.3. @ExternalBean


@ExternalBean은 단순한 마크업 애노테이션으로 '부모 애플리케이션 컨텍스트'에 정의 되어 있는 '외부의' 빈을 인젝션 할 때 사용한다. 예제를 살펴보자:

@Configuration
public abstract class ExternalBeanConfiguration {
  @Bean
  public TestBean james() {
    TestBean james = new TestBean();
    // inject dependency from ann()
    james.setSpouse(ann());
    return james;
  }

  // Will be taken from the parent context
  @ExternalBean
  public abstract TestBean ann();
}

JavaConfig가 @ExternalBean을 만나게 되면, 소유하고 있는 메소드를 오버라이드하여 언제든 메소드를 호출할 수 있도록 한다. '부모 애플리케이션 컨텍스트'는 메소드 이름에 해당하는 bean을 찾아 준다(bean naming과 관련된 챕터에서 보다 자세한 내용을 참조). 이런 방법을, 설정 파일은 순수 자바로 남을 수 있고 익숙하게 리팩터링 할 수 있다.

@ExternalBean이 일반 메소드에도 역시 작동함을 기억하라. 위의 예제는 추상 메소드를 사용하여 실행되지도 않을 쓰레기 코드를 작성하는 것을 방지했다.

@Configuration
public class ExternalBeanOnNormalMethod {

  @ExternalBean
  public TestBean ann(){
      System.out.println("this code will not execute as the method " +
          "will be overriden with a bean look up at runtime");
  }
}

2.4. @ScopedProxy

Spring은 scoped 프록시(자세한 내용은 링크 참조)를 사용하여 scoped 종속성의 사용을 편리하게 했다. 그런 프록시를 생성하는 가장 쉬운 방법은, XML 설정을 사용할 때는 <aop:scope-proxy/> 태그를 사용하는 것이였다. JavaConfig는 그 대안으로 @ScopedProxy 애노테이션을 제공하여 동일한 semantic과 설정 옵션을 사용할 수 있다.

XML을 사용한 레퍼런스의 문서에 있는 예제를 JavaConfig를 사용하여 다음과 같이 작성할 수 있다.

// a HTTP Session-scoped bean exposed as a proxy
@Bean(scope = DefaultScopes.SESSION)
@ScopedProxy
public UserPreferences userPreferences() {
   return new UserPreferences();
}

@Bean
public Service userService() {
   UserService service = new SimpleUserService();
   // a reference to the proxied 'userPreferences' bean
   service.seUserPreferences(userPreferences());
   return service;
}

'Spring JavaConfig > Chapter 2' 카테고리의 다른 글

Components  (0) 2007.07.20
top

Write a comment.


Introduction



원문 : Chapter 1. Introduction

번역

IoC 챕터에서 언급 했듯이, Spring IoC의 핵심은 객체를 Spring 컨테이너에서 어떻게 생성(instantiate)할지, 결합할지(assemble), 관리할지(manage)  정의하는 bean 개념이다. Spring은 자바 코드로 변환할 수 있는 어떠한 메타 데이터라도 사용할 수 있고, XML은 그러한 bean 설정을 기술하는데 가장 널리 쓰이는 방법이다. JDK 5 이상의 버전에서 사용할 수 있는 애노테이션은 실제 소스 코드에 추가 정보를 입력하여 런타임 때 적용할 수 있는 코드를 만들어 낼 수 있기 때문에, 설정 파일의 유력한 후보가 된다.

'Spring JavaConfig > Chapter 1' 카테고리의 다른 글

Introduction  (0) 2007.07.20
top

Write a comment.