spring로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

spring로 검색한 결과
등록일:2008-03-16 16:01:48
작성자:
제목:Spring2.0의 달라진 점 요약


이 글은 스프링 프레임워크의 창시자인 Rod Johnson이 InfoQ에 게제한 spring 2.0: What's New and Why it Matters 기사를 한글로 요약한 글입니다. 원본 기사는 http://www.infoq.com/articles/spring-2-intro 에서 보실 수 있습니다. spring 프레임워크가 버전 1에서 2로 올라서면서 무엇이 어떻게 달라진 것인가 대략적으로만 살펴보는 글이기 때문에 상세한 내용을 원하시는 분은 위 URL로 가셔서 원문을 직접 읽어보세요

스프링 2.0의 주요 변경 사항

  • 설정 확장: 스프링 2.0은 확장 가능한 XML 설정을 지원한다. 이는 새로운 (좀 더 상위의 ) abstrace level에서 스프링 빈을 정의할 수 있다는 것을 의미한다. (역주; XML 스키마를 따로 정의해서 빈 정의를 추상화시킨다는 것을 말하는 것 같다.)
  • AOP 프레임워크에 대한 중요한 발전이 있었다. 좀더 강력하고, 사용하기 쉽도록.. (AspectJ와의 모종의 합의?가 있었던것 같음.)
  • Java 5를 지원하도록 발전되었다. (하지만 국내 환경에서 아직 Java 5는 대세가 아니기 때문에 우리에겐 큰 의미가 없는 것 같다.)
  • 스프링 빈이 다양한 언어에 의해 구현될 수 있게 되었다. (Groovy, JRuby, Beanshell 등) 다른 언어를 사용하면서도 Dependency injection이나 AOP와 같은 스프링 컴포넌트 모델은 유지된다.
  • 포틀릿 MVC 프레임워크와 같은 새로운 기능이 추가되었다. 또한 Java Persistence API (JPA)와의 API 통합, 비동기 태스크 수행 프레임워크가 추가되었다.

Rod Johnson은 이번 기사에서는 XML 설정 확장과 AOP, Java 5에 대해서만 언급을 했습니다..!

XML 설정 확장 기능

단순한 bean 태그로만 구성되어 있는 기존의 스프링 XML 설정으로는 뭔가 한계가 있다. XML 스키마를 따로 만들어주어 복잡한 빈 설정들을 단순하게 만들 수 있다.

예를 들어 스프링 1.x에서는 트랜잭션 처리를 위해 다음과 같은 3개의 빈을 설정해 주어야 했다.

<bean     class="org.springframework...DefaultAdvisorAutoProxyCreator"/>
   <bean class="org.springframework...TransactionAttributeSourceAdvisor">
     <property name="transactionInterceptor                     ref="transactionInterceptor"/> </bean>

  <bean id="transactionInterceptor"      
class="org.springframework...TransactionInterceptor">
     <property name="transactionManager"                     ref="transactionManager"/>
     <property name="transactionAttributeSource">
         <bean class="org.springframework...AnnotationsTransactionAttributeSource">
        </bean>
     </property>
 </bean>

그러나 스프링 2에서는 기본적으로 제공되는 tx 네임스페이스를 사용해서

<tx:annotation-driven />

단 한줄의 태그 삽입만으로 트랜잭션 설정이 종료된다. 물론 tx 네임스페이스를 사용하겠다고 다음과 같이 스프링 설정 XML 문서에 선언해주어야 한다.

이러한 확장 태그는 기존의 bean 정의 태그와 섞여서 함께 사용될 수 있다.

일단 스프링 2.0에서 제공되는 out-of-the-box 네임스페이스의 목록은 다음과 같다.

  • Transaction management ("tx"): Making spring beans transactional becomes significantly easier in spring 2.0, as we have seen. It also becomes easier to define "transaction attributes" mapping transactional behavior onto methods.
  • AOP ("aop"): Specialized tags allow AOP configuration to be much more concise in spring 2.0 than previously, without the IoC container needing to depend on the AOP framework.
  • Java EE ("jee"): This simplifies working with JNDI and other Java EE APIs, as we have seen. EJB lookups gain still more than JNDI lookups.
  • Dynamic languages ("lang"): Simplifies the definition of beans in dynamic languages-a new feature in spring 2.0.
  • Utils ("util"): Simplifies loading java.util.Properties objects and other common tasks.

스프링 2.1 이후에는 더 풍부한 네임스페이스가 제공되어 다양한 영역에서 이러한 단순한 설정을 활용할 수 있게 될 예정이다. 물론, 스프링에서 기본 제공되는 네임스페이스 외에 제 3자 (third party)가 제공하는 네임스페이스를 활용하거나 직접 네임스페이스를 정의해서 사용 가능하다. 대표적인 예가 Acegi Security (2007년 상반기 중에 spring Security로 재탄생될 예정..!) 관련 빈 설정을 한단계 추상화한 예이다.

그러면 어떻게 커스텀 네임스페이스 구현할 수 있을까? 매우 간단하다...! 다음 세 단계를 따라하기만 하면 된다.

  1. XML 스키마를 정의한다. 가장 어려운 스텝이다. 적절한 XML 유틸리티 프로그램으로 작성하면 된다.
  2. 1번에서 정의한 스키마로 부터 BeanDefinition을 생성하기 위해 NamespaceHandler 인터페이스를 구현한다.
  3. spring.handlers 등록 파일을 수정하여 스프링 프레임워크가 새로 생성한 NamespaceHandler를 인식하도록 한다.

http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler

다수의 spring.handlers 파일은 서로 다른 META-INF 디렉토리에 넣어두고 사용할 수 있다. 그러면 스프링이 런타임에 이들을 하나로 병합하게 된다. 스프링 배포에 함께 포함되는 spring.handler 파일을 열어보면 '표준'적인 네임스페이스 설정을 살펴볼 수 있다.

이렇게 XML 확장 태그를 정의해서 사용할 수 있게 된 것은 분명 좋은 일이지만.... 합당한 이유 없이 무분별하게 사용되어서는 안된다. 왜냐 하면 XML 확장 태그를 정의하는 것은 추상화 단계를 더 높이는 일이고 이는 곧 사람들이 뭔가 공부해야 할 것이 늘어난다는 것을 의미하기 때문이다. 이미 스프링의 XML 빈 설정 방식은 수십만의 개발자들에게 친숙해졌는데 분명한 이유 없이 커스텀 네임스페이스를 만들 필요가 있을까....?

다양해진 Bean의 Scope

스프링2.0에서 달라진 것 중의 하나는 bean의 scope가 더 다양해졌다는 것이다. 스프링2.0 이전에는 빈의 스코프 속성으로 Singleton과 Prototype(싱글톤이 아닌것) 2가지가 설정 가능한 것이었다. 그러나 스프링 2.0에서는 커스텀 스코프를 설정할 수 있게 되었다.

웹 어플리케이션에서는 세션에 오브젝트를 담는 방법에 대한 요구 사항이 많았었다. 이 요구는 스프링 2.0의 out of the box에 의해 지원이 될 수 있게 되었다.

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

이 bean 정의에서 스코프로 디폴트값인 singleton이 아닌 session으로 정의되었다. (커스텀 scope는 어떤 이름으로 줘도 상관 없지만 session과 request는 웹 어플리케이션에서 사용하기 위해 예약되었다.)

userPreferences를 getBean()으로 부르게 되면 스프링은 현재 HTTP 세션으로부터 UserPreference의 오브젝트를 가져오게 된다. 만약 세션에 그런 오브젝트가 담겨있지 않으면 새로운 오브젝트를 하나 생성하면 그만이다. 세션으로 부터 오브젝트를 가져오는것을 가능하게 하려면 web.xml에 다음과 같이 리스너를 더 등록해야 한다.

<web-app>
   ...
   <listener>
     <listener-class>
 org.springframework.web.context.request.RequestContextListener
</listener-class>
   </listener>
   ...
</web-app>

그런데 만약.... userPreferences빈을 자신보다 더 긴 라이프사이클을 갖는 다른 빈에다 inject시켜야 하는 경우에는..? 예를 들어 스프링 MVC 컨트롤러에서 다음과 같이 userPref를 사용할 수 있다.

public class UserController extends AbstractController
 {
    private UserPreferences userPreferences;
    public void setUserPreferences(UserPreferences userPreferences)
    {
        this.userPreferences = userPreferences;
    }

   @Override
  protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception
 {
  // do work with this.userPreferences
  // Will relate to current user
  }
   }

이 경우 우린 just in time 인젝션이 가능했으면 좋겠다고 생각하게 된다. (역주; just in time injection? 라이프사이클이 더 짧은 UserPref 오브젝트가 userpref를 사용하려고 하는 순간 그때 오브젝트가 resolve되는... 마치 하이버네이트 같은 ORM의 lazy loading과 같은 개념 같다.)

그런데.. 우리가 착각하고 있는게 하나 있다. 바로 스프링의 빈 인젝션이 static하다고 생각하는 것이고 그래서 stateless하다고 생각하는 것이다. 이건 사실이 아니다. 왜냐면 스프링은 AOP 프레임워크이기 때문이다...!  ㅡㅡ;

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">            <aop:scoped-proxy/>     </bean>

     <!-- a singleton-scoped bean injected with a proxy to the above bean -->     <bean id="userController" class="com.mycompany.web.UserController">          <!-- a reference to the proxied 'userPreferences' bean -->         <property name="userPreferences" ref="userPreferences"/>     </bean> </beans>

이러한 설정으로 이 문제는 쉽게 해결된다.

이제 빈 resolution은 다이내믹하게 발생하게 될 것이다. UserController 안의 userPref 인스턴스는 세션에 있는 UserPref의 오브젝트에 대한 프록시가 된다.

이런 작업들 속에서 세션 객체를 직접적으로 건드릴 필요는 없다. 또한 유닛테스트 때에도 HttpSession 오브젝트에 대한 mock 없이도 테스트가 가능하다. just in time 인젝션에 대한 다른 방법도 있다. (lookup를 사용한건데 이건 그다지 중요한 개념이 아닌 것 같으므로 생략하고 보시길 원하시는 분은 원문을 보시길)

스프링 2.0과 자바 5

스프링 2.0은 자바 5를 지원한다고 하는데 대표적으로 자바5의 generics와 같은 장점들을 활용할 수 있게 만들어준다.

public class DependsOnLists {    private List  plainList;

  private List<Float> floatList;

  public List<Float> getFloatList() {

      return floatList;  }

  public void setFloatList(List<Float> floatList) {    this.floatList = floatList;  }   public List getPlainList() {    return plainList;  }

public void setPlainList(List plainList) {    this.plainList = plainList;  }

}

여기서 plainList는 전통적 방식의 콜렉션이고, floatList는 새로운 방식의 콜렉션이다.

<bean class="com.interface21.spring2.ioc.DependsOnLists">     <property name="plainList">     <list>       <value>1</value>        <value>2</value>       <value>3</value>            </list>     </property>      <property name="floatList">           <list>               <value>1</value>               <value>2</value>               <value>3</value>            </list>      </property> </bean>

이 빈 설정에서 스프링은 floatList를 잘 populate하겠지만

다음 테스트 코드를 보면...

public class GenericListTest extends AbstractDependencyInjectionspringContextTests {

  private DependsOnLists dependsOnLists;

  public void setDependsOnLists(DependsOnLists dependsOnLists) {     this.dependsOnLists = dependsOnLists;   }

  @Override   protected String[] getConfigLocations() {     return new String[] { "/com/interface21/spring2/ioc/inference.xml" };   }

  public void testLists() {     List plainList = dependsOnLists.get

PlainList();     List<Float> floatList = dependsOnLists.getFloatList();     for (Object o : plainList) {         assertTrue(o instanceof String);         System.out.println("Value='" + o + "', class=" +                                 o.getClass().getName());   }     for (Float f : floatList) {         System.out.println("Value='" + f + "', class=" +                                 f.getClass().getName());     }   }

  }

이 테스트 코드의 결과이다.

Value='1', class=java.lang.String Value='2', class=java.lang.String Value='3', class=java.lang.String Value='1.0', class=java.lang.Float Value='2.0', class=java.lang.Float Value='3.0', class=java.lang.Float

향상된 AOP 기능

스프링2.0의 가장 큰 진보는 AOP를 더 쉽고 간단하게 사용할 수 있게 된 것이다. 스프링 팀에게 있어서 AOP는 가장 중요한 가치였다. 왜냐면.. AOP는 전혀 새로운 생각의 방식을 하도록 하기 때문이다. pure oop로는 해결하지 못하는 다양한 문제들도 AOP 적용으로 쉽게 해결되기도 한다.

스프링 2.0 이전의 AOP에선 약간의 결점이 있었다. (귀찮아서 번역 안했습니다. 죄송...ㅜㅜ) Only simple pointcuts could be expressed without writing Java code. There was no pointcut expression language allowing sophisticated pointcuts to be expressed concisely in strings, although RegexpMethodPointcutAdvisor allowed simple regular expression-based pointcuts to be defined.

XML configuration could become complex when configuring complex AOP usage scenarios. The generic element was used to configure the AOP classes; while this was great for consistency, offering DI and other services to aspects as well as classes, it was not as concise as a dedicated configuration approach.

spring AOP was not suited for advising fine-grained objects-objects need to be spring-managed or proxied programmatically.

The performance overhead of a proxy-based approach can be an issue in a small minority of cases.

Because spring AOP separates the proxy and the target (the object being decorated or advised), if a target method invoked a method on the target, the proxy would not be used, meaning that the AOP advice would not apply. The pros and cons of using a proxy-based approach to AOP are beyond the scope of the article: there are some definite positives (such as being able to apply different advice to different instances of the same class), but this is the major negative.

스프링 2.0에서는..... align with AspectJ in spring 2.0 하기로 했다.  왜냐면 AspectJ는 풍부한 포인트컷 표현 언어가 있기 때문에...

이 코드를 보면 이해가 갈 것이다.

@Aspect public class AnnotatedBirthdayCardSender {

  @After("execution(void com.interface21..Person.birthday()) and this(person)")   public void onBirthday(Person person) {     System.out.println("I will send a birthday card to " +             person.getName() + "; he has just turned " +             person.getAge());   } }

복잡한 XML 설정이 아니라 자바5의 문법을 최대한 활용해서 간단하게 AOP를 구현한 모습이다. (역주; 자바 5의 강점을 멋지게 활용한 것 같습니다... 하지만 개발 환경이 자바2라면 소용이 없다는거...)

그럼 XML로 AOP 포인트컷을 정의해주는 방식과 AspectJ의 방식 중 어느것을 사용할 것인가...?

어느것을 사용해도 무방하지만 다음과 같을 경우에는 꼭 XML을 사용할 것.. Use XML if: You are unable to use Java 5, and have no choice. spring 2.0's AOP enhancements, except for processing @AspectJ syntax, work on Java 1.3 and 1.4 as well as Java 5, although you won't be able to write pointcut expressions matching annotations or other Java 5 constructs.

You might want to use the advice in different contexts.

You want to use existing code as advice, and don't want to introduce AspectJ annotations into it: for example, introducing an Observer behavior invoking a method on an arbitrary POJO.

AspectJ 방식의 포인트컷 정의 방식을 사용한 예제는 http://www.infoq.com/articles/spring-2-intro 에 있습니다.



출처 : http://www.wiseant.net/tc/wiseant/177