Understanding Spring @Transactional Annotation: Implementation Principles and Source Code Analysis

This article explains the purpose and inner workings of Spring's @Transactional annotation, detailing how AOP creates proxy objects, the role of BeanPostProcessor, advisors, interceptors, and the TransactionInterceptor, and walks through key source code snippets that manage transaction boundaries.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Understanding Spring @Transactional Annotation: Implementation Principles and Source Code Analysis

At the beginning the author shares a light‑hearted anecdote about a dentist, then dives into the technical discussion of Spring's @Transactional annotation.

The @Transactional annotation enables declarative transaction management in Spring by allowing the framework to open, commit, or roll back transactions automatically through AOP.

Using @Transactional frees developers from writing repetitive transaction code, reduces intrusion into business logic, and lets them focus on core functionality.

The implementation relies on Spring AOP, which uses dynamic proxies. Spring defines a pointcut on methods annotated with @Transactional, creates proxy objects during bean initialization, and applies the proxy logic similar to an @Around advice.

During bean post‑processing, the AnnotationAwareAspectJAutoProxyCreator examines each bean; if the pointcut matches, it creates a proxy via BeanPostProcessor methods such as postProcessAfterInstantiation. The proxy holds a BeanFactoryTransactionAttributeSourceAdvisor instance that represents the transaction pointcut.

When a method is invoked, Spring calls DynamicAdvisedInterceptor#intercept, retrieves the interceptor chain (including TransactionInterceptor), and either directly invokes the target method or creates a CglibMethodInvocation to proceed.

@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
    AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
    if (attributes != null) {
        return parseTransactionAnnotation(attributes);
    } else {
        return null;
    }
}

The TransactionInterceptor#invoke method adapts the call to TransactionAspectSupport.invokeWithinTransaction, which determines the transaction attribute, selects a PlatformTransactionManager, and creates a transaction if necessary.

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
        @Override
        public Object proceedWithInvocation() throws Throwable {
            return invocation.proceed();
        }
    });
}

Inside invokeWithinTransaction, Spring either starts a standard transaction (calling createTransactionIfNecessary, proceeding with the method, handling exceptions to roll back, and finally committing) or uses a CallbackPreferringPlatformTransactionManager to execute a TransactionCallback.

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, methodIdentification(method, targetClass));
        Object retVal = null;
        try {
            retVal = invocation.proceedWithInvocation();
        } catch (Throwable ex) {
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        } finally {
            cleanupTransactionInfo(txInfo);
        }
        commitTransactionAfterReturning(txInfo);
        return retVal;
    } else {
        // callback‑preferring logic omitted for brevity
    }
}

The article concludes by summarizing the full flow, matching the initial hypothesis with diagrams that illustrate how Spring discovers the annotation, creates advisors, builds proxy chains, and finally manages transaction commit or rollback.

Overall, the piece provides a step‑by‑step source‑code‑driven explanation of Spring's declarative transaction mechanism.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaaopspringtransactionaltransaction-management
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.