Transaction Manager, AOP로 설정하기
- transactionManager @Bean 등록
- transactonAdvice, transactionAdvisor @Bean 등록
package com.codesign.base.configure;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@EnableTransactionManagement
@Configuration
@RequiredArgsConstructor
public class DBConfig {
/**
* application.yml 설정으로 자동등록되는 datasource
*/
private final DataSource datasource;
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(datasource);
}
}
Annotation | 설명 |
---|---|
@EnableTransactionManagement | Spring의 <tx:*> XML 네임스페이스에서 지원되는 것과 유사한 Spring의 주석 기반 트랜잭션 관리 기능을 활성화합니다. @Configuration 클래스에서 기존의 필수 트랜잭션 관리 또는 사후 대응 트랜잭션 관리를 구성하는 데 사용됩니다 |
@Configuration | 클래스가 하나 이상의 @Bean 메서드를 선언하고 Spring 컨테이너에 의해 처리되어 런타임에 해당 Bean에 대한 Bean 정의 및 서비스 요청을 생성할 수 있음을 나타냅니다 |
@RequiredArgsConstructor | lombok 에서 제공하는 annotation, 클래스의 final 이나 @NonNull인 필드값을 파라미터로 받는 생성자를자동으로 만들어 줍니다. |
package com.codesign.base.common.aop;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.Collections;
import java.util.List;
@Configuration
@RequiredArgsConstructor
public class TransactionAspect {
/**
* datasource가 주입되어있음
*/
private final PlatformTransactionManager transactionManager;
private final String EXECUTION ="execution(* com.codesign.base..service..*(..))";
@Bean
public TransactionInterceptor transactionAdvice(){
List<RollbackRuleAttribute> rollbackRules = Collections.singletonList(new RollbackRuleAttribute(Exception.class));
RuleBasedTransactionAttribute transactionAttribute = new RuleBasedTransactionAttribute();
transactionAttribute.setRollbackRules(rollbackRules);
transactionAttribute.setName("*");
MatchAlwaysTransactionAttributeSource attributeSource = new MatchAlwaysTransactionAttributeSource();
attributeSource.setTransactionAttribute(transactionAttribute);
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionManager(transactionManager);
interceptor.setTransactionAttributeSource(attributeSource);
return interceptor;
}
@Bean
public Advisor transactionAdvisor(){
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(EXECUTION);
return new DefaultPointcutAdvisor(pointcut, transactionAdvice());
}
}
@Bean | 설명 |
---|---|
transactionAdvice() | rollbackRules - 트랜잭션에서 롤백을 수행하는 규칙(Rule)입니다. RollbackRuleAttribute 생성자의 인자로 Exception 클래스를 지정하였는데요, 자바에서 모든 예외는 Exception 클래스를 상속받기 때문에어떠한 예외가 발생하던 무조건 롤백이 수행됩니다. setName() - 트랜잭션의 이름을 설정합니다. 트랜잭션 모니터에서 트랜잭션의 이름으로 확인이 가능합니다. |
transactionAdvisor() | pointcut - AOP의 포인트컷(pointcut)을 설정합니다. EXPRESSION에 지정한 ServiceImpl 클래스의 모든 메서드를 대상으로 설정합니다. |
@Override
public int addMember(Map<String, Object> param) throws Exception {
MemberVo member = new MemberVo();
member.setMemId("test");
member.setMemName("test");
member.setMemPassword("test123!!");
int result = memberMapper.addMember(member);
if(result > 0){
throw new Exception("등록성공 하지만 롤백할꺼지롱");
}
return memberMapper.addMember(member);
}
등록하지만 throw new Exception("등록성공 하지만 롤백할꺼지롱");
에서 Exception발생되면서 rollback 시킴!