본문 바로가기

스프링

[spring] jaxb_추상화_디폴트의존오브젝트_예외적용_5

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

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

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

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

5.     Com.springsource.junit : junit

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

7.     Mail : java-mail

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

9.     Mysql-connector : Mysql JDBC

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

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

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

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

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

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

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

17.   Spring-test.jar

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

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

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

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

 

레벨의 역할(다음레벨 셋팅 및 전달)은 레벨에게 위임

 

User의 역할은 User에게 User 레벨셋팅

 

 

JAXB sql 엘리먼트 domain

 

Jaxb Sqlmap 엘리먼트 domain

 

JPA, Hibernate, JDBC, JDO 와 같이 변할 수 있으므로 인터페이스

 

 

JDBC 구현

 

 

쿼리 DAO와 분리 DBA에 의한 SQL 리뷰나 튜닝 필요시 해당 파일만 전달. SQL 내용을 변경하더라도 어플리케이션 코드나 DI 설정은 전혀 수정할 필요가 없어짐.

독립적인 파일 XML이 편리한 포맷

 

43, 44. 이제 프로퍼티의 DI를 통해 의존관계를 자유롭게 변경해가면서 기능을 확장할 수 있다. 유연해짐. 하지만, 반대로 적어도 3개의 빈을 등록해줘야 한다는 점이 귀찮게 느껴지기도 한다. 앞으로 클래스가 계속 늘어날텐데 의존관계 설정에 대한 부담을 감수해야 한다. 설령 한동안은 JAXB를 사용하는 SqlReaderHashMap으로 저장해두는 SqlRegistry를 사용할 것이 분명하다고 해도 말이다.

* 이렇게 특정 의존 오브젝트가 대부분의 환경에서 거의 디폴트라고 해도 좋을 만큼 기본적으로 사용될 가능성이 있다면, 디폴트 의존관계를 갖는 빈을 만드는 것을 고려해볼 필요가 있다.

* 디폴트 의존관계 : 외부에서 DI 받지 않는 경우 기본적으로 자동 적용되는 의존관계

 

* XML을 읽어서 Map에 보관하고 필요할 때 제공 관심사의 구분 중 읽어서 보관하기 위한 인터페이스(전략)

- 리턴타입 void : map으로 리턴해줘도 되지만 범용적인 인터페이스가 map을 사용안한다고 한다면?? 바로 Registry에 저장해 주는 방법 채택

- 파일이 없는 경우 등 대부분 복구가 불가능한 예외로 판단하여 예외 없음.

 

 

* XML을 읽어서 Map에 보관하고 필요할 때 제공 관심사의 구분 중 보관되어 있는 Map 중 요청한 쿼리를 제공해주기 위한 인터페이스(전략)

- 레지스트리에서 검색 실패 등으로 다른 레지스트리에 검색 시도 등 복구할 여지가 있어 예외를 던짐.

 

HashMap에 저장하여 키를 받으면 쿼리를 주는 HashMapSqlRegistry

 

 

 

가장 기본이 되는 골격을 가진 기본 클래스이므로 BaseSqlService (템플릿)

7~8. 이 클래스는 추후 다른 클래스에서 확장하여 사용할 가능성이 있는 클래스 이므로 protected

 

 

 

 

데코레이터패턴, 프록시, 트랜잭션을 위한 인터페이스.

트랜잭션  경계설정의 일원화(하나로 만듬)

비즈니스 로직을 담고 있는 서비스 계층 오브젝트에 트랜잭션 경계를 부여하기에 가장 적절한 대상이다.

예를 들어 UserService가 아니라면 UserDao를 직접 사용하지 않고, UserService를 사용하는 것이 바람직하다. 단순 조회나 간단한 수정이라면 직접 UserService외의 서비스 계층 오브젝트에서 UserDao를 사용해도 상관없다. 하지만 등록이나 수정, 삭제가 포함된 작업이라면 다른 모듈의 DAO를 직접 이용할 때 신중을 기해야 한다. 안전하게 사용하려면 다른 모듈의 서비스 계층을 통해 접근하는 방법이 좋다.(트랜잭션 모두 취소 혹은 모두 성공)

- 단순히 레코드 개수를 리턴하는 getCount()를 제외하면 나머지는 독자적인 트랜잭션을 가지고 사용될 가능성이 높다. 따라서 이 4개의 메소드를 추가함.

 

타겟인터페이스 구현

 

 

메일서버 과부하를 막기위한 테스트 스텁

 

DB 접속불가를 위한 목오브젝트를 이용한 테스트

 

목 오브젝트 생성과 add 테스트

 

트랜잭션 테스트

 

 

번거롭게 목, 스텁 오브젝트를 생성하지 않고, 목 프레임웍을 활용한 테스트

 

 

* 디폴트의존오브젝트

- DI 설정이 없을 경우 디폴트로 적용하고 싶은 의존 오브젝트를 생성자에서 넣어준다.

- 외부에서 의존 오브젝트를 주입해주는 것이 아닌, 이렇게 자신이 사용할 디폴트 의존 오브젝트를 스스로 DI 하는 방법도 있다.

- 이렇게 직접 주입해주면 특별히 DI가 필요한 상황이 아닌 대부분의 경우에는 편리하게 사용할 수 있다.

- 모든 의존 오브젝트를 빈으로 일일이 지정할 필요없이 미리 지정한 디폴트 의존 오브젝트를 사용할 수 있게 만드는 것도 좋은 방법이다.

3. 상속사용

- DefaultSqlServiceBaseSqlServicesqlReadersqlRegistry 프로퍼티를 그대로 갖고 있고, 이를 이용해서 원한다면 언제든지 일부 또는 모든 프로퍼티를 변경할 수 있다. 따라서, 대신 사용하고 싶은 구현 오브젝트가 있다면 아래와 같이 프로퍼티를 변경할 수 있다.

 

 

*디폴트의존오브젝트의 단점

- 생성자에서 디폴트 의존 오브젝트를 다 생성해버린다.

- 리스트7-44처럼 설정했다고 해도 DefaultSqlService의 생성자에서 HashMapSqlRegistry 오브젝트가 만들어진 후 설정한 ultraSuperFastSqlRegistry 로 바로 대체된다. 대체되긴 하지만 사용되지 않는 오브젝트가 만들어진다는 점이 조금 꺼림칙하긴 하다. 하지만 디폴트 의존 오브젝트를 갖게 했을 때의 장점이 크기 때문에 오브젝트가 하나쯤 더 만들어지는 부담은 무시할 수도 있다.

- 그러나 디폴트로 만드는 오브젝트가 매우 복잡하고 많은 리소스를 소모한다면 디폴트 의존 오브젝트가 아예 안만들어지게 하는 방법을 사용할 수 있다.

> @PostConstruct 초기화 메소드를 이용해 프로퍼티가 설정됐는지 확인하고 없는 경우에만 디폴트 오브젝트를 만드는 방법을 사용하면 된다.

 

 

3개의 빈을 정의하고 프로퍼티로 연결해야 했던 설정은 한 줄로 바꿀 수 있다.

 

 

* FilePath를 앞서 배운 JdbcTemplate(JdbcTempate편 참조)에서 DataSource 프로퍼티를 UserDao가 대신 DI 받아서, 직접 JdbcTemplate을 만들면서 프로퍼티로 넣어줬던 방법이 있다.(아래 스샷 참조)

- 위 방법이 나쁘지 앉지만 DefaultSqlService에 적용하기에는 적절하지 않다.

  > 디폴트라는 건 다른 명시적인 설정이 없는 경우에 기본적으로 사용하겠다는 의미이다.

  > 반면 설정이 있다면 디폴트는 무시된다.

> DefaultSqlService SqlReader를 통해 의존 오브젝트를 갖고 있기 때문에 FilePath를 사용

  할 수도 있고, 안 할 수도 있다. 따라서 반드시 필요하지도 않는 Path를 프로퍼티로 등록하

  는 것은 바람직하지 못하다.

* 위 스샷처럼 SQL 파일 이름을 매번 바꿔야 할 필요도 없고, 관례적으로 사용할 만한 이름을 정해서 디폴트로 넣어주는건 어떨까?

- 별다른 설정 없이 그대로 사용 가능하다.

- 이렇게 디폴트 값을 주면 JaxbXmlSqlReader를 직접 빈으로 등록해서 사용할 때도 유용할 것이다.

 

스프링의 JdbcTemplateDataSource 주입