다음과같이 성공한 사건에 대해선 Commit, 조금이라도 실패한 사건에 대해선 Rollback
이렇게 일련의 처리행위에 대해 완벽한 성공을 보장하는 처리단위를 트랜잭션 이라고한다
스프링에서는 DB에 데이터가 적재되거나 취소되는 상황에 대해 AOP를 이용해 쉽게 지원해준다
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에 따라 다양한 전략이 매핑된다
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)로서 등록이된다