Spring中@Transactional什么时候开启事务?

在使用注解事务的情况时,Spring会把每个方法的执行封装为AOP执行过程。每次执行被事务注解方法时,会判断是否有必要创建事务。如果创建事务成功,则继续调用业务逻辑方法。事务是在方法执行最开始阶段创建的,因此方法要越小越好。

事务的执行入口是TransactionInterceptor的invoke方法

    @Override
    public Object invoke(final 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, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

而invoke是实现MethodInterceptor接口,而MethodInterceptor最后会封装成ReflectiveMethodInvocation实例执行,调用proceed方法。

public interface MethodInterceptor extends Interceptor {
    Object invoke(MethodInvocation invocation) throws Throwable;
}

TransactionInterceptor是继承扩展了

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

}

TransactionAspectSupport是比较关键的类,里面实现了事务很多业务逻辑。包括是否必要创建事务createTransactionIfNecessary,执行事务调用invokeWithinTransaction,选用什么事务管理器determineTransactionManager。

从invokeWithinTransaction方法名可以看出,在事务中执行调用,这个方法很关键,实现事务主要逻辑。

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
            throws Throwable {

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

        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();//执行真正的业务操作,也就是DAO方法
            }
            catch (Throwable ex) {
                // target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }

    //省略
    ...

}

createTransactionIfNecessary告诉我们在必要的时候才创建事务

    protected TransactionInfo createTransactionIfNecessary(
            PlatformTransactionManager tm, 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);
    }

其中invocation.proceedWithInvocation()方法是一个around advice,会进行链式调用。DAO类方法就在这里执行的,执行完后,真正事务提交在commitTransactionAfterReturning中。

    protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
            }
            txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
        }
    }

你可能感兴趣的:(Spring)