본문 바로가기

스프링

[Spring AOP] 프록시_타깃_데코레이터패턴

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

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

3.     Com.springsource.junit : junit

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

5.     Mail : java-mail

6.     Mysql-connector : Mysql JDBC

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

8.     Spring-aop : 스프링 기능 자체의 aop

9.     Spring-bean : 스프링 빈을 활용하는 경우 필요. 스프링의 XML 설정파일과 자바 애노테이션을 파싱 하는데 필요한 클래스 포함

10.   Spring-context : 스프링 코어를 확장한 많은 클래스가 들어 있는데 모든 클래스는 EJB, JNDI(Java Naming Directory Interface), JMX용 클래스와 연동하는데 applicationcontext기능을 사용해야 하며 스프링 리모팅 클래스, 동적 스크립팅 언어(제이루비, 그루비등)와 연동하는 클래스, 빈 유효성검증(JSR-303) API, 스케줄링을 하는 클래스도 포함되어 있다.

11.   Spring-core : 모든 스프링 모듈에서 필요한 모듈. 다른 스프링 모듈에서 사용하는 공통 클래스가 포함됨.

12.   Spring-dao : EmpltyResultDataAccessException 등 사용을 위한 jar

13.   Spring-expression : 스프링 표현언어(SpEL) 지원 클래스 포함.

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

15.   Spring-test.jar

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

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

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

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

 

Level에게 다음레벨이 무엇인지에 대한 정보 역할 위임

 

user객체에 다음레벨에 대한 정보 역할 위임

 

 

여러 데이터 엑세스 기술이 사용될 수 있으므로 인터페이스(전략 부분)

 

전략은 인터페이스 구현, 템플릿은 JdbcTemplate에게

 

 

 

 

JavaMail로 매번 메일전송 테스트를 하는 것은 서버의 부하가 크기에 아무것도 안하는 클래스 생성

 

 

비즈니스 로직과 트랜잭션 로직을 분리하여 깔끔하게 나누었지만(메소드분리), 트랜잭션을 담당하는 기술적인 코드가 버젓이 UserService 안에 자리 잡고 있다.

트랜잭션 코드를 밖으로 뽑아내면된다.

-       UserService는 현재 UserServiceTest에서 사용하고 있지만, 실전에서는 다른 클래스 혹은 모듈에서 사용할 것이다. UserService는 구체적인 구현 클래스로 트랜잭션을 뺀다면, UserService를 사용하는 클라이언트는 트랜잭션 기능이 빠진 UserService를 사용할 것이다. 구체적인 구현 클래스를 직접 참조하는 경우의 전형적인 단점이다.

>  직접 사용하는 것이 문제라면 실제 사용할 오브젝트의 클래스 정체는 감춘채 인터페이스를 통해 간접으로 접근하여 구현 클래스를 외부에서 변경하도록 할 수 있다.

 

 

 

 

 

 

 

 

 

UserServiceTx : UserServiceImpl를 대신하기 위한 것이 아닌, 트랜잭션 경계설정의 책임만을 갖고, 비즈니스로직은 UserServiceImpl에게 위임한다.

프록시(UserServiceTx) : 클라이언트가 사용하려고 하는 실제 대상인 것처럼 위장하여 클라이언트의 요청을 받아주는 것(타깃과 같은 인터페이스로 구현)

*  타깃(UserServiceImpl) : 프록시를 통해 요청을 위임받아 처리하는 실제 오브젝트

 

프록시 사용 목적 2가지

클라이언트가 타깃에 접근하는 방법제어(프록시 패턴)

타깃에 부가적인 기능을 부여(데코레이터 패턴)

데코레이터 패턴

타깃에 부가적인 기능을 런타임 시 다이내믹하게 부여해주기 위해 프록시를 사용하는 패턴

데코레이터 : 제품을 여러겹으로 포장하고 장식을 붙이는 방법으로 실제 내용물은 동일하지만 부가적인 효과를 부여한다는 의미

인터페이스를 구현한 타깃과 여러 개의 프록시를 사용할 수 있다. 프록시가 여러 개인 만큼 순서를 정해서 단계적으로 위임하는 구조로 만들면 됨.

타깃의 코드를 손대지 않고, 클라이언트가 호출하는 방법도 변경하지 않은 채로 새로운 기능을 추가할 때 유용한 방법

아래 구현한 타깃인 UserServiceImpl에 트랜잭션 부가기능을 제공해주는 UserServiceTx를 추가한 데코레이터 패턴을 적용한 것이라고 볼 수 있다.

프록시 패턴

프록시패턴의 프록시 : 타깃의 기능을 확장하거나 추가하지 않는다. 대신 클라이언트가 타깃에 접근하는 방식을 변경해준다.

>  클라이언트의 요청을 받으면 네트워크를 통해 원격의 오브젝트를 실행하여 결과를 받아 클라이언트로 하여금 원격 오브젝트에 대한 접근 방법을 제공

 

레벨이 할일은 레벨에게 Service의 분기처리가 짧아진다.

 

 

User의 레벨값 세팅은 레벨에게 물어봐 User값 세팅

 

 

다른 DataAccess프로그램을 사용할 수 있으므로 인터페이스

 

 

JDBC 기술 구현 전략 > 인터페이스, 템플릿 > JdbcTemplate

 

 

아래 처럼 트랜잭션을 적용한 서비스를 생성했으면 userService라는 대표적인 빈 아이디는 UserServiceTx 클래스로 변경해주고, 비즈니스 로직은 UserServiceImpl 을 주입시켜줘 비즈니스로직을 위임한다.

17. userService : UserServiceTx는 데코레이터가 되고 DI를 통해 타깃(UserServiceImpl) 주입

 

 

메일서버의 기능이 검증됐다면 매번 부하를 주는 테스트를 할 필요가 없으므로 스프링 MailSender 인터페이스 사용

 

 

클라이언트가 사용할 핵심 메소드만 인터페이스로 생성.

데코레이터 패턴. , 타깃 클래스(비즈니스 로직)와 프록시(트랜잭션 설정)을 구현하기 위한 인터페이스

 

 

19, 24~26. 트랜잭션 관련코드도 제거되어야함.

트랜잭션과 관련된 코드 제거. User라는 도메인 정보를 가진 비즈니스 로직에만 충실한 깔끔한 코드.

비즈니스 로직에만 충실하여 트랜잭션의 지식이 부족한 개발자라도 개발이 가능.

>  즉, 데코레이터 패턴의 타겟 클래스가됨.

 

 

 

 

 

15. UserService를 구현한 비즈니스 로직 오브젝트를 DI 받는다.

16, 19, 24. 비즈니스 로직을 모두 DI받은 오브젝트에게 위임한다.

12, 22. 트랜잭션 경계설정이 필요한 메소드에 트랜잭션을 적용한다.

 

데코레이터 패턴의 프록시 : 클라이언트가 사용하려고 하는 타겟의 위장클래스.

-       데코레이터 패턴 프록시의 문제점

인터페이스의 모든 메소드를 구현해 위임하도록 코드를 만들어야 한다.

>  트랜잭션이 필요할 때마다 모든 메소드에 트랜잭션 경계설정 코드가 중복된다.

 

29. @Autowired : 기본적으로 타입이 일치하는 빈을 찾고, 타입이 같다면(UserService) 아이디 값과 동일한 필드명에 주입된다.

30. UserServiceImpl 을 가져온 이유는 MailSenderDI 해줄 대상을 알고 있는 오브젝트를 가져온 것임.(application-context.xml, 53. MockMailSender 수정자메소드 DI)

 

 

91. upgradeAllOrNothing 테스트는 로직 테스트 목적이 아닌, 트랜잭션 기술이 적용됐는지 학습테스트다. 기존에는 TestUserService 오브젝트를 만들어서 필요한 의존 오브젝트를 넣어주고 테스트 했었다. 이제 TestUserService는 트랜잭션 롤백의 확인을 위한 비즈니스 로직(super.upgradeLevel(user))UserServiceImpl에 있기에 이를 상속하여, UserServiceTx 오브젝트에 수동 DI하여 테스트 수행.

115. DB인서트 실패를 위한 TestService