본문 바로가기

스프링

[spring] aop_어노테이션 트랜잭션_클래스프록시_10

@Transactional 애노테이션의 타깃은 메소드와 타입이므로, 메소드/클래스/인터페이스에서 사용할 수 있다.

> 특정 메소드만 격리수준을 변경한다거나 제한시간을 두는 등의 필요가 생겼을 때 aoptx 태그를 이용하려면 매우 복잡해진다. , 하나의 메소드에 다른 트랜잭션 속성을 부여하기 위해 새로운 포인트컷, 어드바이스, 어드바이저를 지정하고 해당 메소드를 다른 포인터컷에서는 제외시켜야 하는 등의 복잡한 방법을 사용해야 한다. 반면에 @Transactional을 사용하면 간단히 해결됨.

 

@Transactional 애노테이션을 트랜잭션 속성으로 지정하면 스프링은 @Transactional 애노테이션을 트랜잭션 속성 정보로 사용하도록 지정하면, @Transactional이 부여된 모든 오브젝트를 자동으로 타깃 오브젝트로 인식하며, 이 때 사용되는 포인트컷은 TransactionalAttributeSource Pointcut이다.

TransactionalAttributeSourcePointcut

스스로 표현식과 같은 선정 기준을 갖고 있지 않고, @Transactional이 타입, 메소드 레벨이든 상관없이 부여된 빈 오브젝트를 모두 찾아서 포인트컷의 선정 결과로 돌려준다.

>  따라서, @Transactional 어노테이션은 위처럼 트랜잭션 속성을 정의할 수도 있고, 동시에 포인트컷의 자동등록에도 사용됨

 

 

따라서 메소드 혹은 타입(class, interface) 별로 유연한 속성 제어가 가능하지만, 코드는 지저분해지고, 애노테이션이 반복적으로 부여해주는 바람직하지 못한 결과를 가져올 수 있다.

@TransactionalFailback(대체) 정책

>  타깃 메소드, 클래스, 인터페이스 메소드, 인터페이스의 순서에 따라 @Transactional이 적용됐는지 차례로 확인하고, 가장 먼저 발견되는 속성정보를 사용하게 한다.

 

 

 

1.     [5], [6] @Transactional 이 존재하는지 확인하는 첫번 째 후보.

2.     [4] 두번째 후보

3.     [2], [3] 세번째 후보

4.     [1] 마지막

위와 같이 대체 정책을 잘 활용해서 애노테이션 최소한으로 사용하면서 세밀한 제어가 가능하다.

기본적으로 @Transactional 적용 대상은 클라이언트가 사용하는 인터페이스가 정의한 메소드 이므로 인터페이스에 두는 것이 바람직하다.

*  하지만, 인터페이스를 사용하는 프록시 방식의 AOP가 아닌 방식으로 트랜잭션을 적용하면 인터페이스에 정의한 @Transactional은 무시되기 때문에 안전하게 타깃 클래스에 @Transactional을 두는 방법을 권장함.

 

 

트랜잭션 애노테이션 설정 엄청 간단함!

@Transactional

설정이 직관적이고 간단하므로 사용하는 경우가 많다.

>  다만 트랜잭션 적용 대상을 손쉽게 파악할 수 없고, 사용 정책을 잘 만들어두지 않으면 무분별하게 사용되거나 자칫 빼먹을 위험도 있다.

 

* 클래스 프록시 사용

> 인터페이스를 구현하지 않은 클래스에서 주로 사용됨.

> 인터페이스를 구현한 클래스에도 강제로 적용이 가능하다. 이때는 반드시 클래스에 @Transactional을 부여해줘야 한다. 인터페이스에 적용하면 트랜잭션이 적용되지 않는다.

* 클래스 프록시 제약사항

> 클래스 프록시는 상속을 통해 프록시를 생성하기 때문에 상속이 불가능한 final 클래스에는 적용되지 않는다.

> 상속을 통해 프록시를 만들기 때문에 클래스의 생성자가 두 번 호출된다. 이 때문에 생성자에 리소스를 할당하는 것 같은 중요한 작업은 피해야 한다.

> 인터페이스에 이용하지 않기 때문에 수정자 같은 DB작업이 없는 메소드에도 불필요한 트랜잭션이 실행되므로 시간과 리소스 낭비가 발생한다.

 

 

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 : 스프링 빈을 활용하는 경우 필요. 스프링의 XML 설정파일과 자바 애노테이션을 파싱 하는데 필요한 클래스 포함

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

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

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

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

17.   Spring-test.jar

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

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

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

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

19.   Spring-dao : EmpltyResultDataAccessException 등 사용을 위한 jar 제거됨. 스프링 4에서는 필요없음.(@Transactional이 정상작동 안함)

 

 

레벨이 할일은 레벨에게 위임

 

 

User의 레벨셋팅은 User에게 위임 서비스의 분기처리가 줄어듬

 

 

JDBCHibernate,JDA,JDO,JPA 등의 DB Access API를 사용하기 위함

 

 

JDBC 구현 JdbcTemplate 템플릿의 구현이 되어있는 스프링 것 사용

 

 

트랜잭션 어노테이션 활용. 데코레이터 패턴 및 다이내믹 프록시 사용을 위한 서비스

UserService 인터페이스에 @Transactional을 적용한 이유 UserServiceImple, TestUserService 양쪽에 트랜잭션이 적용될 수 있기 때문. 인터페이스 방식의 프록시를 사용하는 경우 인터페이스에 적용하는 것이 맞다.

*  get으로 시작하지 않는 메소드에는 디폴트 속성. get으로 시작하는 메소드에게는 읽기전용 속성 부여

 

이젠 사용하지 않는 내가 구현한 트랜잭션 어드바이스

 

타겟 서비스 구현

 

 

만약 타깃에 @Transactional을 선언한다면 실패한다. 왜냐하면 대체 정책 순서는 타깃 클래스가 인터페이스보다 우선하므로 모든 메소드의 트랜잭션을 디폴트 속성을 갖게 된다. 따라서, 디폴트 속성의 프록시 빈이 생성되어, 읽기전용 테스트는 실패하게 되는 것임.

 

 

어노테이션 트랜잭션 설정. 어드바이저, 어드바이스, 포인트컷 어노테이션을 이용한 트랜잭션 속성정보가 등록됨. 가장 간단한 설정

 

목오브젝트를 활용한 메일발송 테스트