본문 바로가기

스프링

092.WEB_모델과바인딩검증_프로퍼티에디터_프로토타입빈

1.     Com.springsource.javax.activation : Spring java-mail

2.     Com.springsource.javax.inject-1.0.0 : 프로토타입 프로퍼티 에디터를 위한 jar. @Inject, Provider인터페이스<PropertyEditorSupport> 지원

3.     Com.springsource.javax.mail : Spring java-mail

4.     Com.springsource.javax.servlet.jsp.jstl : JstlView

5.     Com.springsource.org.aopalliance : Spring ProxyFactoryBean

6.     Com.springsource.org.aspectj.tools : AspectJExpressionPointcut 포인트컷 표현식 지원

7.     Com.springsource.org.cator.core : 자동으로 자바 오브젝트를 XML로 변환 지원.

8.     Com.springsource.org.cator.xml : 자동으로 자바 오브젝트를 XML로 변환 지원.

9.     Com.springsource.junit : junit

10.   Commons-logging : Spring-context가 사용

11.   Jackson-annotation : MappingJackson2JsonView

12.   Jackson-core : MappingJackson2JsonView

13.   Jackson-databind : MappingJackson2JsonView

14.   Mail : java-mail

15.   Mockito : 목 프레임워크 중 Mockito

16.   Mysql-connector : Mysql JDBC

17.   Org.springframework.context.support : Spring java-mail

18.   Org.springframework.oxm : Object-XML Mapping. 마샬러 빈을 지정해 모델에서 변환에 사용할 오브젝트를 지정해주면, OXM마샬러를 통해 모델 오브젝트를 XML로 변환해서 뷰의 결과로 사용할 수 있음.

19.   Spring-aop : 스프링 기능 자체의 aop, Spring ProxyFactoryBean

20.   Spring-bean : 스프링 코어와 함께 의존성 주입 제공 (Core Container)

21.   Spring-context : 스프링 코어, BeanFactory를 확장한 어플리케이션 컨텍스트 구현, 리소스 로드 및 국제화 지원(Core Container)

22.   Spring-core : 다른 스프링 모듈이 사용하는 유틸리티(Core Container)

23.   Spring-expression : EL 확장 Bean속성(배열, 컬렉션 포함).(Core Container)

24.   Spring-jdbc : 스프링이 지원하는 jdbc.

25.   Spring-test.jar

-       @RunWith : Junit 프레임워크의 테스트 실행방법을 확장시 사용.

-       SpringJUnit4ClassRunner : 어플리케이션컨텍스트를 만들고 관리하는 확장 클래스

-       @ContextConfiguration(경로) : 자동으로 만들어줄 어플리케이션 컨텍스트 설정파일

26.   Spring-tx : DuplicateKeyException.class 파일 존재 및 스프링 트랜잭션

27.   Spring-web : ContextLoaderListener 내장 루트 컨텍스트(서비스,DAO)

28.   Spring-webmvc : SpringMVC를 위한 리졸버, 모델앤뷰 등 지원

 

 

* 프로퍼티 에디터는 매번 새로만든다. 싱글톤 빈으로 등록될 수 없다. 프로퍼티 에디터에 setValue()를 이용해 오브젝트를 넣은 후 getAsText()로 변환된 문자열을 가져오는 식(상태값을 가지고 있다.)이다. 프로퍼티 에디터에 의해 타입이 변경되는 오브젝트는 상태를 갖고 있기 때문에 싱글톤은 안된다.

 

그런데 프로퍼티 에디터가 다른 스프링 빈을 참조해야 한다면? 프로토타입 빈은 매번 빈 오브젝트를 요청해서 새로운 오브젝트를 가져올 수 있으면서 DI도 가능하니 이런 경우 적격이다.

*어떤 경우에 프로퍼티 에디터가 다른 스프링 빈을 참조할까?

> ID를 가지고 DB에 도메인 오브젝트 전체를 과정에 필요하다. 물론 DAO를 통해 해당 도메인 오브젝트를 가져오게 할 수도 있지만, 폼에서 사용되는 모델 오브젝트의 특정 프로퍼티가 다른 도메인 오브젝트 타입인 경우가 많다. 이런 경우를 생각해보자.

 

* 어떤 경우에 프로퍼티 에디터가 다른 빈을 참조해야할까?

> 회원가입 폼에 유저정보와 code셀렉트박스(1, admin/2, user..) 파라미터 중 코드 정보는 Code도메인에 매핑될 수 없다. 어떻게 이를 바인딩하는지 살펴보자.

- User도메인에 userType을 추가하여 파라미터를 받고, 셀렉트시에는 코드 정보를 가져온다. 가장 간단하지만, 도메인 오브젝트에 임시 저장용 프로퍼티가 추가되어 더러워지고, @RequestParam을 사용한다 하더라도 메소드 선언이 길어진다.

* 모조 오브젝트 프로퍼티 에디터(아래 참조

 

테스트 디스패처 서블릿을 위한 인터페이스

 

* 번거로운 XML 설정 대신 AbstractDispatcherServletTest를 사용

25. DispatcherServlet 초기화시 ServletConfig 오브젝트를 만들어 초기화해야함.

50. ContextRoot 값이 있을 때 추가해줌

54. setServletPath : 컨텍스트 root를 넣을 수 있도록 셋팅

58. requesturi 정보와 get,post mothod 셋팅 및 리스판스 객체 생성

 

81. 테스트 DispatcherServlet Init

 

 

 

FakeCode를 만든 이유는 모조오브젝트의 단점을 보완하기 위함. 필요한 id값을 가져오는 메소드를 제외한 이외의 모든 메소드를 오버라이드해서 예외를 던지면 모조 오브젝트의 필요없는 값을 업데이트하거나 참조하는 실수를 사전에 방지할 수 있게 해준다.

 

33. registerCustomEditor : AnnotationMethod~AdapterWebDataBinder를 만들고 적용타입을 가진 바인딩 대상이 나오면 항상 프로퍼티 에디터가 적용되어 userType만 코드 도메인에 담기고 값을 뱉음.

* 이렇게 아이디값만 가지고 있는 오브젝트를 모조 오브젝트(fakeObject)라고 하고, 이런 오브젝트를 만드는 에디터를 모조 프로퍼티 에디터라고 부른다.

> 단점 : 모조 오브젝트를 서비스계층으로 옮기는 것은 위험한 발상이다. 실수로 userType의 이름을 꺼내려고 한다든가. 수정된 user를 업데이트하면서 Code 오브젝트도 같이 업데이트하면 예상치 못한 문제가 발생할 것이다.

 

이런식으로 user테이블의 코드값만 변경할 때 사용된다. 단 위의 단점처럼 userType에 연결되어 있는 Code 오브젝트를 다른 용도로 활용하거나 강제 업데이트를 하지 않아야한다는 제한이 있다.

 

* 프로토타입 도메인 오브젝트 프로퍼티 에디터

> 바인딩을 위해 임시 id저장용 userTypeId 등은 안만들어도 되며, 모조 오브젝트가 아닌 DB에서 읽어온 완전한 Code 오브젝트로 변환해준다.(프로퍼티에디터가 CodeDao 같은 빈을 DI 받아 사용해야한다는 뜻)

> 따라서 다른 빈을 DI 받는 오브젝트는 자신도 빈이어야 하기 때문에 프로퍼티 에디터를 빈으로 등록해줘야 한다. 싱글톤 빈으로 만들어 공유하면 안되기 때문에 프로토타입 빈으로 만들어야한다.

19,35. 프로토타입 빈을 등록하여 DB에서 가져온 Code값을 활용 가능해진다.

26. UserController에서 사용할 수 있도록 javax.inject.Provider를 이용해 선언

29. Provider를 이용해 프로토타입 빈의 새 오브젝트를 가져온다. 매번 DB에서 새로 오브젝트를 읽어와 성능에 미미한 부하를 주지만, JPA나 하이버네이트처럼 엔티티 단위의 캐싱 기법이 발달한 경우라면, 메모리에서 바로 가져올 수 있으므로 DB에 부하를 주는 걱정은 하지 않아도 된다.

* 맵이나 코드정보를 추가로 받는 도메인객체를 새로 만드는 방법도 있지만 장기적으로 유지보수의 부담이 늘며 버그도 증가할 가능성이 높다. 번잡해보여도 장기적으로 코드의 중복은 없어지고, 변경이 일어날 장소는 한 군데로 집중되어 프로젝트 막판에도 자신감 있게 코드를 다룰 수 있을 것이다.