[Spring] Custom Transactional Annotation in AOP

가끔 프로그래밍을 하다보면 다음과 같이 앞뒤로 (Before, After) Code duplication 이 발생한다. 이를 AOP를 이용하여 깔끔하게 코드 중복을 정리할 수 있는데 원리(rule)는  @Transactional Annotation과 비슷하다.

Before Job: begin Transaction

Processed : execute queries

After Job : end Transaction

Spring에서도 Interceptor를 위한 AOP를 구현해보자

Interceptor에 대해 이해가 잘 가지 않는다면 다음 wiki를 참고하길 바란다.

http://en.wikipedia.org/wiki/Interceptor_pattern

Step 1. xml bean configuration

<beans xmlns=”http://www.springframework.org/schema/beans&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns:p=”http://www.springframework.org/schema/p&#8221;
xmlns:mvc=”http://www.springframework.org/schema/mvc&#8221; xmlns:context=”http://www.springframework.org/schema/context&#8221;
xmlns:tx=”http://www.springframework.org/schema/tx&#8221; xmlns:aop=”http://www.springframework.org/schema/aop&#8221;
xsi:schemaLocation=”
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
default-autowire=”byName”>
<aop:aspectj-autoproxy />
<context:component-scan base-package=”org.simple.aop”> 

Step2. Annotation 생성

@Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TransactionApply {

}

Step3. Aspect Bean 만들기

package org.simple.aop;

@Aspect
@Component
public class SimpleAspect {

@Around(“execution(public * *(..)) && @annotation(txApply)“)
public Object transactionAround(ProceedingJoinPoint joinPoint, TransactionApply txApply) throws Throwable {

Object retVal = null;
// TODO : Begin Transaction
try {

retVal = joinPoint.proceed();

} catch (Throwable t) {

// TODO : Transaction Roll Back

throw t;

}

//TODO : end Transaction
return retVal;

}

}

package org.simple.aop;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TransactionApply {
}

Step4. Apply Custom Annotation

@Service(“SimpleBO”)

public class SimpleBOImpl implements SimpleBO {

@TransactionApply
@Override
public Object updatePolicy(Object param) {

// TODO : select, update, delete in joinPoint.proceed

}

}

Tip : 만약 bean creation 시 다음과 같은 오류가 발생한다면 cglib의 version을 2.2 이상으로 올리는 것을 추천한다.

Caused by: java.lang.NoSuchMethodError: net.sf.cglib.proxy.Enhancer.setInterceptDuringConstruction(Z)V

위 issue의 원인은 cglib 2.0.2 version에서 setInterceptDuringConstruction이라는 Method가 없기 때문이다.

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-full</artifactId>
<version>2.0.2</version>
</dependency>

2.2 이상으로 설정하면 오류가 사라지며 bean 생성이 정상적으로 이루어짐을 확인할 수 있다.

<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>

Attention : this exam requires cglib version higher than 2.2, aspectj dependency

광고

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중