Talk about EnableTransactionManagement of spring tx

  spring

Order

This article mainly studies the EnableTransactionManagement of spring tx.

EnableTransactionManagement

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/annotation/EnableTransactionManagement.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
     * opposed to standard Java interface-based proxies ({@code false}). The default is
     * {@code false}. <strong>Applicable only if {@link #mode()} is set to
     * {@link AdviceMode#PROXY}</strong>.
     * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
     * Spring-managed beans requiring proxying, not just those marked with
     * {@code @Transactional}. For example, other beans marked with Spring's
     * {@code @Async} annotation will be upgraded to subclass proxying at the same
     * time. This approach has no negative impact in practice unless one is explicitly
     * expecting one type of proxy vs another, e.g. in tests.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate how transactional advice should be applied.
     * <p><b>The default is {@link AdviceMode#PROXY}.</b>
     * Please note that proxy mode allows for interception of calls through the proxy
     * only. Local calls within the same class cannot get intercepted that way; an
     * {@link Transactional} annotation on such a method within a local call will be
     * ignored since Spring's interceptor does not even kick in for such a runtime
     * scenario. For a more advanced mode of interception, consider switching this to
     * {@link AdviceMode#ASPECTJ}.
     */
    AdviceMode mode() default AdviceMode.PROXY;

    /**
     * Indicate the ordering of the execution of the transaction advisor
     * when multiple advices are applied at a specific joinpoint.
     * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
     */
    int order() default Ordered.LOWEST_PRECEDENCE;

}
  • EnableTransactionManagement has three attributes: proxyTargetClass, AdviceMode, and order; ; It import Transactional ManagementConfigurationSelector
  • Setting proxyTargetClass to true indicates that a subclass-based proxy (CGLIB), set to false to indicate the use of an interface-based proxy, which defaults to false
  • AdviceMode indicates which kind of transactional advice to use, with PROXY and ASPECTJ. The default is AdviceMode.PROXY

TransactionManagementConfigurationSelector

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/annotation/TransactionManagementConfigurationSelector.java

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    /**
     * Returns {@link ProxyTransactionManagementConfiguration} or
     * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
     * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
     * respectively.
     */
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:
                return new String[] {AutoProxyRegistrar.class.getName(),
                        ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {determineTransactionAspectClass()};
            default:
                return null;
        }
    }

    private String determineTransactionAspectClass() {
        return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
                TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
                TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
    }

}
  • Transactional ManagementConfigurationSelector inherits the abstract class adviceModeImportSelector, which covers selectImports. This method returns the class name to be created according to AdviceMode. If it is PROXY mode, it returns AutoProxyRegISTrar.class.getName (), ProxyTransactionManagementConfiguration.class.getName (); If it is ASPECTJ mode, it returns Transactional ManagementConfigurations. JTA _ Transaction _ Aspect _ Configuration _ Class _ Name or Transactional ManagementConfigurations . Transaction _ Aspect _ Configuration _ Class _ Name

AbstractTransactionManagementConfiguration

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.java

@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

    @Nullable
    protected AnnotationAttributes enableTx;

    /**
     * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
     */
    @Nullable
    protected PlatformTransactionManager txManager;


    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        this.enableTx = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
        if (this.enableTx == null) {
            throw new IllegalArgumentException(
                    "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
        }
    }

    @Autowired(required = false)
    void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
        if (CollectionUtils.isEmpty(configurers)) {
            return;
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
        }
        TransactionManagementConfigurer configurer = configurers.iterator().next();
        this.txManager = configurer.annotationDrivenTransactionManager();
    }


    @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
        return new TransactionalEventListenerFactory();
    }

}
  • AbstractTransactionManagementConfiguration provides a general structure for the EnableTransactionManagement annotation. Here, txManager is initialized and TransactionAleventListenerForBehavior is created. It has three subclasses, namely ProxyTransactionManagementConfiguration, AspectJTransactionManagementConfiguration, AspectJJTransactionManagementConfiguration

ProxyTransactionManagementConfiguration

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.java

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }
        return interceptor;
    }

}
  • ProxyTransactionManagementConfiguration inherits AbstractTransactionManagementConfiguration, where it registers BeanActionTransactionAttributeSourceAdvisor, TransactionAttributeSource (AnnotationTransactionAttributeSource)、TransactionInterceptor

AnnotationTransactionAttributeSource

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/annotation/AnnotationTransactionAttributeSource.java

public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
        implements Serializable {

    private static final boolean jta12Present;

    private static final boolean ejb3Present;

    static {
        ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
        jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
        ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
    }

    private final boolean publicMethodsOnly;

    private final Set<TransactionAnnotationParser> annotationParsers;


    /**
     * Create a default AnnotationTransactionAttributeSource, supporting
     * public methods that carry the {@code Transactional} annotation
     * or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
     */
    public AnnotationTransactionAttributeSource() {
        this(true);
    }

    /**
     * Create a custom AnnotationTransactionAttributeSource, supporting
     * public methods that carry the {@code Transactional} annotation
     * or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
     * @param publicMethodsOnly whether to support public methods that carry
     * the {@code Transactional} annotation only (typically for use
     * with proxy-based AOP), or protected/private methods as well
     * (typically used with AspectJ class weaving)
     */
    public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
        this.publicMethodsOnly = publicMethodsOnly;
        if (jta12Present || ejb3Present) {
            this.annotationParsers = new LinkedHashSet<>(4);
            this.annotationParsers.add(new SpringTransactionAnnotationParser());
            if (jta12Present) {
                this.annotationParsers.add(new JtaTransactionAnnotationParser());
            }
            if (ejb3Present) {
                this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
            }
        }
        else {
            this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
        }
    }

    //......

}
  • The parameterless constructor of Annotate TransactionAttributeSource sets publicMethodsOnly to true, and also creates SpringTransactionAnnotate Parser.

TransactionInterceptor

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionInterceptor.java

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

    /**
     * Create a new TransactionInterceptor.
     * <p>Transaction manager and transaction attributes still need to be set.
     * @see #setTransactionManager
     * @see #setTransactionAttributes(java.util.Properties)
     * @see #setTransactionAttributeSource(TransactionAttributeSource)
     */
    public TransactionInterceptor() {
    }

    /**
     * Create a new TransactionInterceptor.
     * @param ptm the default transaction manager to perform the actual transaction management
     * @param attributes the transaction attributes in properties format
     * @see #setTransactionManager
     * @see #setTransactionAttributes(java.util.Properties)
     */
    public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
        setTransactionManager(ptm);
        setTransactionAttributes(attributes);
    }

    /**
     * Create a new TransactionInterceptor.
     * @param ptm the default transaction manager to perform the actual transaction management
     * @param tas the attribute source to be used to find transaction attributes
     * @see #setTransactionManager
     * @see #setTransactionAttributeSource(TransactionAttributeSource)
     */
    public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
        setTransactionManager(ptm);
        setTransactionAttributeSource(tas);
    }


    @Override
    @Nullable
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be {@code null}.
        // The TransactionAttributeSource should be passed the target class
        // as well as the method, which may be from an interface.
        Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        // Adapt to TransactionAspectSupport's invokeWithinTransaction...
        return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
    }


    //---------------------------------------------------------------------
    // Serialization support
    //---------------------------------------------------------------------

    private void writeObject(ObjectOutputStream oos) throws IOException {
        // Rely on default serialization, although this class itself doesn't carry state anyway...
        oos.defaultWriteObject();

        // Deserialize superclass fields.
        oos.writeObject(getTransactionManagerBeanName());
        oos.writeObject(getTransactionManager());
        oos.writeObject(getTransactionAttributeSource());
        oos.writeObject(getBeanFactory());
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        // Rely on default serialization, although this class itself doesn't carry state anyway...
        ois.defaultReadObject();

        // Serialize all relevant superclass fields.
        // Superclass can't implement Serializable because it also serves as base class
        // for AspectJ aspects (which are not allowed to implement Serializable)!
        setTransactionManagerBeanName((String) ois.readObject());
        setTransactionManager((PlatformTransactionManager) ois.readObject());
        setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
        setBeanFactory((BeanFactory) ois.readObject());
    }

}
  • TransactionInterceptor inherits the abstract class TransactionAspectSupport and implements MethodInterceptor, Serializable interface. Its invoke method first reads the targetClass, and then calls the invokeWithinTransaction method of the abstract class TransactionAspectSupport.

TransactionAspectSupport

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionAspectSupport.java

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    // NOTE: This class must not implement Serializable because it serves as base
    // class for AspectJ aspects (which are not allowed to implement Serializable)!

    private static final Object DEFAULT_TRANSACTION_MANAGER_KEY = new Object();

    private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
            new NamedThreadLocal<>("Current aspect-driven transaction");

    @Nullable
    protected static TransactionInfo currentTransactionInfo() throws NoTransactionException {
        return transactionInfoHolder.get();
    }

    public static TransactionStatus currentTransactionStatus() throws NoTransactionException {
        TransactionInfo info = currentTransactionInfo();
        if (info == null || info.transactionStatus == null) {
            throw new NoTransactionException("No transaction aspect-managed TransactionStatus in scope");
        }
        return info.transactionStatus;
    }


    protected final Log logger = LogFactory.getLog(getClass());

    @Nullable
    private String transactionManagerBeanName;

    @Nullable
    private PlatformTransactionManager transactionManager;

    @Nullable
    private TransactionAttributeSource transactionAttributeSource;

    @Nullable
    private BeanFactory beanFactory;

    private final ConcurrentMap<Object, PlatformTransactionManager> transactionManagerCache =
            new ConcurrentReferenceHashMap<>(4);

    //......        
    /**
     * General delegate for around-advice-based subclasses, delegating to several other template
     * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
     * as well as regular {@link PlatformTransactionManager} implementations.
     * @param method the Method being invoked
     * @param targetClass the target class that we're invoking the method on
     * @param invocation the callback to use for proceeding with the target invocation
     * @return the return value of the method, if any
     * @throws Throwable propagated from the target invocation
     */
    @Nullable
    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {

        // If the transaction attribute is null, the method is non-transactional.
        TransactionAttributeSource tas = getTransactionAttributeSource();
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // Standard transaction demarcation with getTransaction and commit/rollback calls.
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                // This is an around advice: Invoke the next interceptor in the chain.
                // This will normally result in a target object being invoked.
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }

        else {
            final ThrowableHolder throwableHolder = new ThrowableHolder();

            // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
                    TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                    try {
                        return invocation.proceedWithInvocation();
                    }
                    catch (Throwable ex) {
                        if (txAttr.rollbackOn(ex)) {
                            // A RuntimeException: will lead to a rollback.
                            if (ex instanceof RuntimeException) {
                                throw (RuntimeException) ex;
                            }
                            else {
                                throw new ThrowableHolderException(ex);
                            }
                        }
                        else {
                            // A normal return value: will lead to a commit.
                            throwableHolder.throwable = ex;
                            return null;
                        }
                    }
                    finally {
                        cleanupTransactionInfo(txInfo);
                    }
                });

                // Check result state: It might indicate a Throwable to rethrow.
                if (throwableHolder.throwable != null) {
                    throw throwableHolder.throwable;
                }
                return result;
            }
            catch (ThrowableHolderException ex) {
                throw ex.getCause();
            }
            catch (TransactionSystemException ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                    ex2.initApplicationException(throwableHolder.throwable);
                }
                throw ex2;
            }
            catch (Throwable ex2) {
                if (throwableHolder.throwable != null) {
                    logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                }
                throw ex2;
            }
        }
    }

    //......
}
  • The invokeWithinTransaction method of TransactionAspectSupport is not null for TransactionAttribute and PlatformTransactionManager is a transaction in TransactionCallback of type CallBackReferringPlatformTransactionManager; Others use the standard gettransaction and commit/rollback calls mode for transaction processing, calling createTransactionIfNecessary execution, completetransactionaftertimekeeping when exception occurs, cleanupTransactionInfo when final, and committransactionaftererrorning at last.

createTransactionIfNecessary

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionAspectSupport.java

    /**
     * Create a transaction if necessary based on the given TransactionAttribute.
     * <p>Allows callers to perform custom TransactionAttribute lookups through
     * the TransactionAttributeSource.
     * @param txAttr the TransactionAttribute (may be {@code null})
     * @param joinpointIdentification the fully qualified method name
     * (used for monitoring and logging purposes)
     * @return a TransactionInfo object, whether or not a transaction was created.
     * The {@code hasTransaction()} method on TransactionInfo can be used to
     * tell if there was a transaction created.
     * @see #getTransactionAttributeSource()
     */
    @SuppressWarnings("serial")
    protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
            @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

        // If no name specified, apply method identification as transaction name.
        if (txAttr != null && txAttr.getName() == null) {
            txAttr = new DelegatingTransactionAttribute(txAttr) {
                @Override
                public String getName() {
                    return joinpointIdentification;
                }
            };
        }

        TransactionStatus status = null;
        if (txAttr != null) {
            if (tm != null) {
                status = tm.getTransaction(txAttr);
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                            "] because no transaction manager has been configured");
                }
            }
        }
        return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
    }

    /**
     * Prepare a TransactionInfo for the given attribute and status object.
     * @param txAttr the TransactionAttribute (may be {@code null})
     * @param joinpointIdentification the fully qualified method name
     * (used for monitoring and logging purposes)
     * @param status the TransactionStatus for the current transaction
     * @return the prepared TransactionInfo object
     */
    protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
            @Nullable TransactionAttribute txAttr, String joinpointIdentification,
            @Nullable TransactionStatus status) {

        TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
        if (txAttr != null) {
            // We need a transaction for this method...
            if (logger.isTraceEnabled()) {
                logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
            }
            // The transaction manager will flag an error if an incompatible tx already exists.
            txInfo.newTransactionStatus(status);
        }
        else {
            // The TransactionInfo.hasTransaction() method will return false. We created it only
            // to preserve the integrity of the ThreadLocal stack maintained in this class.
            if (logger.isTraceEnabled()) {
                logger.trace("Don't need to create transaction for [" + joinpointIdentification +
                        "]: This method isn't transactional.");
            }
        }

        // We always bind the TransactionInfo to the thread, even if we didn't create
        // a new transaction here. This guarantees that the TransactionInfo stack
        // will be managed correctly even if no transaction was created by this aspect.
        txInfo.bindToThread();
        return txInfo;
    }
  • The createTransactionIfNecessary method determines whether a new transaction needs to be created based on TransactionAttribute, and then executes prepareTransactionInfo to create TransactionInfo and bindToThread.

completeTransactionAfterThrowing

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionAspectSupport.java

    /**
     * Handle a throwable, completing the transaction.
     * We may commit or roll back, depending on the configuration.
     * @param txInfo information about the current transaction
     * @param ex throwable encountered
     */
    protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                        "] after exception: " + ex);
            }
            if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                try {
                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by rollback exception", ex);
                    throw ex2;
                }
            }
            else {
                // We don't roll back on this exception.
                // Will still roll back if TransactionStatus.isRollbackOnly() is true.
                try {
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    ex2.initApplicationException(ex);
                    throw ex2;
                }
                catch (RuntimeException | Error ex2) {
                    logger.error("Application exception overridden by commit exception", ex);
                    throw ex2;
                }
            }
        }
    }
  • CompleteTransactionAfterThrowing is used to handle abnormal situations. It determines whether to rollback or commit based on TransactionInfo and Throwable information.

cleanupTransactionInfo

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionAspectSupport.java

    /**
     * Reset the TransactionInfo ThreadLocal.
     * <p>Call this in all cases: exception or normal return!
     * @param txInfo information about the current transaction (may be {@code null})
     */
    protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
        if (txInfo != null) {
            txInfo.restoreThreadLocalStatus();
        }
    }
  • CleanupTransactionInfo is used to reset TransactionInfo for ThreadLocal.

commitTransactionAfterReturning

spring-tx-5.1.6.RELEASE-sources.jar! /org/springframework/transaction/interceptor/TransactionAspectSupport.java

    /**
     * Execute after successful completion of call, but not after an exception was handled.
     * Do nothing if we didn't create a transaction.
     * @param txInfo information about the current transaction
     */
    protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
        if (txInfo != null && txInfo.getTransactionStatus() != null) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
            }
            txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
        }
    }
  • CommitTransactionAfterErrorTransaction is used to commit a transaction when the method executes successfully.

Summary

  • EnableTransactionManagement has three attributes: proxyTargetClass, AdviceMode, and order;; It import Transactional ManagementConfigurationSelector; Setting proxyTargetClass to true indicates that a subclass-based proxy (CGLIB), set to false to indicate the use of an interface-based proxy, which defaults to false; AdviceMode indicates which kind of transactional advice to use, with PROXY and ASPECTJ. The default is AdviceMode.PROXY
  • Transactional ManagementConfigurationSelector inherits the abstract class adviceModeImportSelector, which covers selectImports. This method returns the class name to be created according to AdviceMode. If it is PROXY mode, it returns AutoProxyRegISTrar.class.getName (), ProxyTransactionManagementConfiguration.class.getName (); If it is ASPECTJ mode, it returns Transactional ManagementConfigurations. JTA _ Transaction _ Aspect _ Configuration _ Class _ Name or Transactional ManagementConfigurations . Transaction _ Aspect _ Configuration _ Class _ Name
  • ProxyTransactionManagementConfiguration inherits AbstractTransactionManagementConfiguration, where it registers BeanActionTransactionAttributeSourceAdvisor, TransactionAttributeSource (AnnotationTransactionAttributeSource)、TransactionInterceptor
  • TransactionInterceptor inherits the abstract class TransactionAspectSupport and implements MethodInterceptor, Serializable interface. Its invoke method first reads the targetClass, and then calls the invokeWithinTransaction method of the abstract class TransactionAspectSupport.
  • The invokeWithinTransaction method of TransactionAspectSupport is not null for TransactionAttribute and PlatformTransactionManager is a transaction in TransactionCallback of type CallBackReferringPlatformTransactionManager; Others use the standard gettransaction and commit/rollback calls mode for transaction processing, calling createTransactionIfNecessary execution, completetransactionaftertimekeeping when exception occurs, cleanupTransactionInfo when final, and committransactionaftererrorning at last.

doc