http://www.onjava.com/pub/a/onjava/2005/05/11/spring.html

onjava_logo.jpg

ONJava.com Published on ONJava.com (http://www.onjava.com/)
http://www.onjava.com/pub/a/onjava/2005/05/11/spring.html
See this if you're having trouble printing code examples

내가 Spring을 사랑하는 다섯가지#

by Bruce A. Tate, coauthor of Spring: A Developer's Notebook
05/11/2005

약 2년전 나는 Hibernate사이트에 두드러지게 언급된 Spring프로젝트를 시험해 보았다. 마치 옛날의 카약(kayak)같은 느낌이 들었다. 이것은 나에게 완벽하게 내 마음에 들었다. 하드코딩식의 기업용 개발을 위해 Spring은 나의 네번째 자바책인 Spring: A Developer's Notebook을 만들도록 나의 프로그래밍에 많은 부분을 차지하게 되었다. 이 글은 내가 왜 그렇게 했는지 당신에게 말하는것이다.

1. Spring은 좀더 나은 영향력을 제공한다.#

Spring을 사용하면 코드의 각각의 라인으로 좀더 많은 일을 할수 있다. 당신은 Spring으로 많은 부분에 추가적인 영향을 보이는것을 알게될것이다. 하지만 가장 큰것은 퍼시스턴스에서이다. 이것은 Hibernate 데이터접근 객체의 메소드이다.

public List getReservations( ) {
  return getHibernateTemplate( ).find("from Reservation");
}

당신이 보지 않은것이 무엇인지 주의하라. 여기엔 트랜잭션 처리부분이 없다. Spring은 그것을 다루기 위해 당신에게 설정코드를 빌드하게 한다. 당신은 세션을 닫음으로써 자원들을 관리하지는 않을것이다. 당신은 당신 자신만의 설정을 가지지도 않을것이다. 당신은 예외들이 체크되지 않기 때문에 이 레벨에서 예외들을 관리하지는 않을것이다. 당신은 가장 선호하는 위치에서 그것들을 관리하는데 자유로울 것이다. 이것은 Spring을 사용하지 않고 Hibernate메소드를 사용하는 방법을 보이는 것이다.

public List getBikesOldWay( ) throws Exception {
  List bikes = null;
  Session s = null;
  try {
    s = mySessionFactory.openSession( );
    bikes = s.find("from Bike");
  }catch (Exception ex) {
    //handle exception gracefully
  }finally {
    s.close( );
  }
  return bikes;
}

Spring은 나에게 여러가지 영향력을 준다. 그래서 나는 좀더 빨리 코드를 작성하고 관리를 덜 할수 있게 되었다.

2. Spring은 POJO프로그래밍을 가능하게 한다.#

EJB 2.x의 붕괴(debacle)이후, 우리는 귀찮은 모델과 함께 각각 그리고 모든 빈을 침법하지 않는 기업용 서비스를 표현하기 위한 방법을 찾고 있다. 물론 우리는 트랜잭션, 보안, 퍼시스턴스 그리고 때때로 원격(remoting)을 필요로 한다. EJB를 사용하면 나는 API를 확장하는 법을 배워야 하고 새로운 툴과 배치 처리를 통해 작업을 수행해야만 한다. 나는 컨테이너에 의해 제공되는 서비스에 종속되었었다. Spring을 사용하면 나는 나 자신의 서비스와 퍼시스턴스 프레임워크를 선택할수 있다. 나는 POJO에서 프로그램을 하고 설정파일을 가지고 그것들을 기업용 서비스에 추가할수 있다.

Spring: A Developer's Notebook에서 나는 세션빈또는 엔터티빈 대신에 RentaBike애플리케이션을 빌드했다. 나는 나의 POJO를 hibRentaBike라고 부른다. 이것은 나의 데이터접근 객체처럼 제공한다. 나는 다른곳에 서비스를 추가한다. 컨텍스트라 불리는 Spring설정파일은 컨테이너내 bean의 모든것(bean이 필요로 하는 프라퍼티와 서비스)을 담는 XML파일이다.

목표(target)는:

<bean id="rentaBikeTarget" class="com.springbook.HibRentABike">
  <property name="storeName">
    <value>Bruce's Bikes</value>
  </property>
  <property name="sessionFactory">
    <ref local="sessionFactory"/>
  </property>
  <property name="transactionManager">
    <ref local="transactionManager"/>
  </property>
</bean>

인터셉터(interceptor)는:


<bean name="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
    <ref local="transactionManager"/>
  </property>
  <property name="transactionAttributeSource">
    <value>
      com.springbook.RentABike.transferReservation=
      PROPAGATION_REQUIRED,-ReservationTransferException
      com.springbook.RentABike.save*=PROPAGATION_REQUIRED
      com.springbook.RentABike.*=PROPAGATION_REQUIRED,readOnly
    </value>
  </property>
</bean>

프록시(proxy)는:

<bean id="rentaBike" class="org.springframework.aop.framework.ProxyFactoryBean">
  <property name="proxyInterfaces">
    <value>com.springbook.RentABike</value>
  </property>
  <property name="interceptorNames">
    <value>transactionInterceptor,rentaBikeTarget</value>
  </property>
</bean>

세가지의 다른 형태(proxy, target, interceptor)의 bean이 있다. 프록시는 POJO와 POJO에 의해 필요한 어떠한 서비스를 호출할것이다. 인터셉터는 서비스를 호출하는 코드를 포함한다. 그들은 목표(target)내 각각의 메소드를 처리하기 위한 방법을 정의한다. 누군가가 트랜잭션적인 인터셉터를 호출하는 프록시를 호출하는 RentaBike에 접근할 필요가 있다. 목표(target)는 인터셉터로 반환하고 프록시나 프록시의 호출자로 반환하는 것을 수행한다.

spring_fig1.gif

Figure 1. POJO programming in action

당신은 POJO밖에서 프로그램을 빌드하고 그것을 설정한다. 그리고 Spring은 당신을 위해 나머지를 숨겨준다. 나는 POJO프로그래머이다.

3. DI(Dependency Injection)은 테스트기능을 도와준다.#

Spring은 DI(Dependency Injection)라는 디자인패턴을 통해 당신의 테스트기능을 향상시킨다. 소비자(consumer)가 의존성에 의존할때 당신은 소비자(consumer)에서 프라퍼티를 생성할 것이다. Spring은 소비자(consumer)와 서비스를 생성할것이고 서비스의 값으로 소비자의 프라퍼티를 셋팅한다. 다른 방법으로 말하면 Spring은 컨텍스트내 bean의 생명주기를 관리하고 의존성을 해석한다. 이것은 Spring을 사용하지 않은 DI 예제이다. 첫번째, 이것은 소비자이고 애플리케이션을 위한 원시형태의 뷰처럼 제공된다.

public class CommandLineView {

  private RentABike rentaBike;

  public CommandLineView( ) {rentaBike = new ArrayListRentABike("Bruce's Bikes")}

public void setRentABike(RentABike rentABike){

  this.rentABike = rentABike;

}

  public void printAllBikes( ) {
    System.out.println(rentaBike.toString( ));
    Iterator iter = rentaBike.getBikes().iterator( );
    while(iter.hasNext( )) {
      Bike bike = (Bike)iter.next( );
      System.out.println(bike.toString( ));
    }
  }

  public static final void main(String[] args) {
    CommandLineView clv = new CommandLineView( );
    clv.printAllBikes( );
  }

}

다음, 이것은 모델인 서비스이다. 이것은 array list의 간단한 구현물이다. 이것은 모델(RentaBike)에 대해 의존성을 가진다.

interface RentABike {
List getBikes( );
Bike getBike(String serialNo);
}

public class ArrayListRentABike implements RentABike {
   private String storeName;
   final List bikes = new ArrayList();
   public ArrayListRentABike(String storeName) {
      this.storeName = storeName;
      bikes.add(new Bike("Shimano""Roadmaster"20"11111"15"Fair"));
      bikes.add(new Bike("Cannondale""F2000 XTR"18"22222",12,"Excellent"));
      bikes.add(new Bike("Trek","6000"19"33333"12.4"Fair"));
   }

   public String toString() { return "RentABike: " + storeName; }
   public List getBikes() { return bikes; }
   public Bike getBike(String serialNo) {
      Iterator iter = bikes.iterator();
      while(iter.hasNext()) {
         Bike bike = (Bike)iter.next();
         if(serialNo.equals(bike.getSerialNo())) return bike;
      }
      return null;
   }
}

이것은 어셈블러(assembler)이다. The code in bold is the dependency injection. 어셈블러와 서비스와 소비자를 구체화한다. 그리고 rentaBike프라퍼티를 셋팅함으로써 의존성을 해결한다.

public class RentABikeAssembler {
  public static final void main(String[] args) {
    CommandLineView clv = new CommandLineView( );
    RentABike rentaBike = new ArrayListRentABike("Bruce's Bikes");
    clv.setRentaBike(rentaBike);
    clv.printAllBikes( );
  }
}

물론 Spring은 결국 어셈블러의 역활을 채울것이다. 만약 당신이 인터페이스로 서비스를 포장한다면 당신은 컨테이너로 인터페이스의 어떤 구현물을 집어넣을수 있을것이다.

DI는 당신을 제작물 의존성과 테스트 의존성을 코딩하도록 할것이다. 예를 들면 이 예제는 뷰를 좀더 쉽게 테스트하게 만드는 스텁객체를 생성한다. (스텁이나 모의객체에 대한 좀더 다양한 정보는 "Mocks Aren't Stubs."을 읽어보길 바란다.)

당신은 RentaBike의 Hibernate구현물과 array list버전의 구현물을 보았다. 나는 전체 Hibernate구현물에서 나의 모든 사용자 인터페이스 테스트를 실행하기를 원하지 않을지도 모른다.. 대신에 나는 다른 방법으로 array list를 사용해서 인터페이스를 간단하게 구현한다.

DI는 나를 제품버전(HibRentaBike), 개발버전(ArrayListRentaBike 리스트), 테스트버전(모의객체)으로 묶는다. 내가 자바로 코딩을 할때 나는 닿기 어려운 지점(hard-to-reach places)으로 모의객체를 얻기 위해 DI를 사용할 것이다.

4. IoC는 JDBC를 단순화한다.#

JDBC애플리케이션은 보기 흉하고 장황하며 지루하다. 좋은 추상화 레이어는 그것을 도울수 있다. Spring은 당신을 쿼리를 가지고 디폴트 JDBC메소드와 많은 단조루운 작업을 제거하기 위해 익명(anonymous) 내부 클래스를 커스터마이징하게 한다. 이것은 간단한 JDBC예제이다.

JdbcTemplate template = new JdbcTemplate(dataSource)
final List names = new LinkedList();

template.query("SELECT USER.NAME FROM USER"
  new RowCallbackHandler() { 
      public void processRow(ResultSet rsthrows SQLException {
        names.add(rs.getString(1));
      }
  }
)

template.query메소드의 생각은 디폴트 JDBC메소드와 같다. Spring은 result set내 각각의 라인을 위해 익명내부클래스내 processRow메소드를 수행할것이다. 당신은 컨텍스트내 데이터소스를 설정한다. 당신은 statement나 connection을 열고 닫는것과 데이터소스 설정하기 또는 트랜잭션 맵핑하기등에 대해 걱정할 필요가 없다. 당신은 외부 result set을 정의하지 않고 Spring이 당신의 SQLException을 체크되지 않은 예외의 공통적인 집합으로 접기 때문에 가장 낮은 단계의 예외를 관리하지도 않는다. 루비나 스몰토크와같은 다른 언어는 코드블럭으로 종종 Inversion of Control을 사용한다. 하지만 이것이 자바내에서는 그다지 공통적인 사항이 아니다.

5. Spring 관련 커뮤니티가 번창하다.#

몇몇 오픈소스 프로젝트는 유용하게 되기 위해 특별한 행위를 할 필요가 없다. 예를 들면 JUnit같은게 그 예이다. Spring같은 가벼운 컨테이너는 힘찬 커뮤니티가 필요하다. Spring은 당신이 찾을수 있고 많은 것을 얻을수 있는 가장 활발한 커뮤니티중에 하나를 가지고 있다.

  • 서비스 : Spring을 사용하면 당신은 보안으로부터 시스템관리, 워크플러어까지 수백가지의 다른 서비스를 찾을수 있다.퍼시스턴스를 위해 당신은 JDO, Hibernate, TopLink, JDBC 또는 OJB로 플러그인 할수 있다.
  • 지원및 교육 : 많은 독립적인 컨설턴트들은 Spring서비스를 제공한다. 그리고 당신은 세계적으로 예외적인 훈련을 받을수 있다.
  • 향상 : Spring은 한해에 다양한 버전의 릴리즈를 내놓는다. 프레임워크내 완벽한 테스팅과 깔끔하게 계산된 확장은 각각의 릴리즈가 좋은 품질을 가지고 있다는것을 의미한다. Spring은 벌써 Hibernate3에 대한 지원을 한다. 그리고 새로운 web flow프레임워크(Spring Web Flow)를 제공한다.
  • 상업적인 지원 : 나와 같은 저자는 Spring으로 책을 쓴다. 당신은 Spring에 대한 5권의 책을 찾을수 있다. 그리고 몇몇 Spring내용보다 다양한 업체들이 Spring을 지원한다. Geronimo 와 Hibernate같은 많은 오픈소스 프레임워크가 Spring을 위한 특별한 지원을 한다.

Spring커뮤니티는 프레임워크 사용을 좀더 쉽게 만든다. 나는 Spring개발자를 고용하고 그들을 훈련시킬수 있다. 나는 나의지식을 채우기 위해 책을 읽을수 있다. 그리고 내가 하길 원하는 모든것을 위한 컴포넌트를 얻을수 있다. 나는 닫힌 가벼운 컨테이너를 위한 커뮤니티를 찾을수는 없었다.

자원들#

  • You can find the Spring framework here.
  • Spring: A Developer's Notebook and its code formed the foundation of this article. It's a developer notebook, so pay close attention to the errata page, and definitely use the sample code to make things easier.

In April 2005, O'Reilly Media, Inc., released Spring: A Developer's Notebook.

  • For more information, or to order the book, click here.

Bruce A. Tate is a kayaker, mountain biker, and father of two. In his spare time, he is an independent consultant in Austin, Texas. He is the author of four books, including the bestselling Bitter Java, and the recently released Better, Faster, Lighter Java, from O'Reilly.

Copyright (c) 2005 O'Reilly Media, Inc.

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
jpg
onjava_logo.jpg 17.2 kB 1 06-Apr-2006 09:45 61.83.100.237
gif
spring_fig1.gif 10.4 kB 1 06-Apr-2006 09:45 61.83.100.237
« This page (revision-1) was last changed on 06-Apr-2006 09:45 by UnknownAuthor