스프링부트 해부학 : AOP(번외) - @Transactional

정윤성·2022년 6월 13일
0

스프링부트 해부학

목록 보기
13/20

역할


다음과같이 성공한 사건에 대해선 Commit, 조금이라도 실패한 사건에 대해선 Rollback
이렇게 일련의 처리행위에 대해 완벽한 성공을 보장하는 처리단위를 트랜잭션 이라고한다

스프링에서는 DB에 데이터가 적재되거나 취소되는 상황에 대해 AOP를 이용해 쉽게 지원해준다

@Transactional

TransactionInterceptor.class

public Object invoke(MethodInvocation invocation) throws Throwable  {
	return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
      @Override
      @Nullable
      public Object proceedWithInvocation() throws Throwable {
      	return invocation.proceed();
     }
     @Override
		public Object getTarget() {
			return invocation.getThis();
		}
		@Override
		public Object[] getArguments() {
			return invocation.getArguments();
		}
	});
}

@Transactional은 실제 Advice에 등록되고 위 메서드를 통해 Proxy객체가 된다
이때 Platform에 따라 다양한 전략이 매핑된다

  • JpaTranscationManager
  • JdbcTranscationManager

invokeWithinTransaction에 대해서 조금더 살펴보자

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
    	final InvocationCallback invocation) throws Throwable {
        
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    }
}
public abstract class AbstractFallbackTransactionAttributeSource
		implements TransactionAttributeSource, EmbeddedValueResolverAware {
 	@Override
	@Nullable
	public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {  
    	...
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        ...
    }
    
    @Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    	...
    	TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
        ...
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        ...
    }
}
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {
	@Override
	@Nullable
	protected TransactionAttribute findTransactionAttribute(Method method) {
		return determineTransactionAttribute(method);
	}

	@Nullable
	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			TransactionAttribute attr = parser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}
}

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
	...
	@Override
	@Nullable
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}
    ...
}

위의 과정을 거쳐 @Transacational이 달린 Method -> Class순으로 Aspect를 적용시킨다

다시 Asepect처리과정으로 돌아오면

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
    	final InvocationCallback invocation) throws Throwable {
    	 ...
         Reactive인경우의 처리방식(ReactiveTransacationSupport사용)
         ...
         Object retVal;
         try {
         	retVal = invocation.proceedWithInvocation(); // Method실행
         }
         catch (Throwable ex) {
			completeTransactionAfterThrowing(txInfo, ex); // Rollback
			throw ex;
         }
         finally {
         	cleanupTransactionInfo(txInfo);
         }
         ...
         commitTransactionAfterReturning(txInfo);
         return retVal;
    }
    ...
}

실제 처리는 Method를 invoke하고 Exception발생시 Rollback, 정상처리 될경우 Commit을 진행한다 이때 Rollback과 Commit은 위에서 설명했던 PlatformTransactionManage에게 처리를 위임한다


그렇다면 TransacationInterceptor는 언제 등록될까 ?

AbstractSingletonProxyFactoryBean.class

@Override
public void afterPropertiesSet() {
	...
    proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));
    ...
}

TransacationProxyFacgtoryBean.class

@Override
protected Object createMainInterceptor() {
	...
	this.transactionInterceptor.afterPropertiesSet();
    if (this.pointcut != null) {
    	return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
    }
    else {
    	return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
    }
    ...
}

위처럼 SingletonProxyFactoryBean이 생성될 때 Main Interceptor(Advice)로서 등록이된다

정리

  1. @Transcational또한 Advisor의 일종이다
  2. PlatformTransactionManager에게 Jpa, JDBC 등의 플랫폼에 맞게 처리를 위임시킨다
profile
게으른 개발자

0개의 댓글