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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
