트랜잭션 이용 & AOP 이용

2017. 1. 9. 17:21Programming/Spring

트랜잭션 적용 순서:

1) pom.xml으로 라이브러리 로딩

2) root-context로 트랜잭션 찾을 패키지 지정

3) @Transactional로 트랜잭션 적용



1) pom.xml으로 라이브러리 로딩


<pom.xml>

1
2
3
4
5
6
7
8
 
<!-- transaction을 위한 설정 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
 
cs



2) root-context로 트랜잭션 찾을 패키지 지정

<root-context.xml>
1
2
3
4
5
6
7
8
9
10
 
<bean id="transactionManager" class="org.springframework.jdbc
.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource"></property>
</bean>
              
<!-- bean 중에서 @Transactional을 찾는 기술 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.spring.dao"/>
<context:component-scan base-package="com.spring.service"/>
 
cs




3) @Transactional로 트랜잭션 적용


<MemberService.java>

1
2
3
4
5
6
7
8
9
10
11
 
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
public interface MemberService {
//출력:read, 추가:add, 삭제:remove, 변경:modify
              
       @Transactional(readOnly=true//select만 가능케
       public Member readMember(int num) throws Exception;
 
       @Transactional(rollbackFor=Exception.class//중간에 에러시 전부 취소
       public void modifyMember(Member member, MemberAlbumVo albumVo) throws Exception;
 
cs



AOP(관점 지향):
인터셉터와 비슷하게 메소드 호출 전/후에 특정한 동작하도록(=advise) 할 수 있음
메소드를 형태에 따라 구분하여 이용한다.

구분1) com.spring.controller.*.*(*): 요청을 받는 메소드
구분2) com.spring.dao.*.insert*(): insert 쿼리를 실행하는 메소드
구분3) com.spring.service.*.modify*(): dml 쿼리와 연계된 dao 실행하는 메소드(트랜잭션)


순서:
1) pom.xml으로 라이브러리 로딩
2) aop가 위치한 패키지 지정
3) aop 구현


1) pom.xml으로 라이브러리 로딩

<pom.xml>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
 
<!-- aop를 위한 설정 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
 
cs



2) aop가 위치한 패키지 지정

<root-context.xml>
1
2
3
4
5
6
 
<!-- spring-aop를 사용할 클래스 위치 지정 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<aop:config></aop:config>
<context:component-scan base-package="com.spring.aop"></context:component-scan>
 
cs



3) aop 구현

<com.spring.aop>  >  <DaoAdvice.java>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
// aop 과정
//1) Proxy 객체 생성 범위 결정
//2) Dao 객체 주변에 Proxy 객체(advice) 생성
//3) Dao에 요청 들어오면 검사
 
@Component //Root-context.xml에서 bean으로 등록할 수 있게 해줌
@Aspect    //aop 기술을 사용하겠다(aop:aspectj-autoproxy가 검사)
public class DaoAdvice {
              private static final Logger logger = LoggerFactory.getLogger(DaoAdvice.class);
              //Join Points 기술에는 Before,after,AfterReturning,AfterThrowing,Around가 있다.
              
              @Before("execution(* com.spring.dao.*.*(..))")
              public void startLog(JoinPoint joinPoint){
                            logger.info("************************** start **************************");
                            logger.info("method path: "+joinPoint.getSignature()); //실행되는 메소드의 위치
                            Object params[] = joinPoint.getArgs(); //주고 받는 파라미터 출력
                                          for(Object param : params){
                                                        logger.info(param.toString());
                                          }
              }
              @After("execution(* com.spring.dao.*.*(..))")
              public void endLog(JoinPoint joinPoint){
                            logger.info("method path: "+joinPoint.getSignature());
                            logger.info("************************** end **************************");
              }
              
 
              //@Around는 굉장히 강력한 AOP 기능으로 메소드 실행 제어 가능
              @Around("execution(* com.spring.dao.*.*(..))")
              public Object timeLog(ProceedingJoinPoint pjp)throws Throwable{
                            //해당 메소드의 실행 시간 출력 가능
                            logger.info("timeLog start");
                            long startTime = System.currentTimeMillis();
                            Object result = pjp.proceed();
                            long endTime = System.currentTimeMillis();
                            logger.info("timeLog end time:("+((endTime-startTime)/1000.0)+"초)");
                            return result;
              }
}
 
cs