美文网首页
Spring源码分析之事物管理

Spring源码分析之事物管理

作者: 穹柏 | 来源:发表于2022-10-28 23:25 被阅读0次

概览

事物执行流程

Spring声明式事物流程.png

类与类的交互

TransactionInterceptor: 事物代理入口

TransactionAttributeSource :事物方法扫描、注解信息解析

TransactionManager:持有连接信息,负责事物开启、回滚、savepoint等

image.png

初始化

TransactionAutoConfiguration: 引入TransactionManagementConfigurationSelector以及代理模式

TransactionManagementConfigurationSelector:引入ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration:生成BeanFactoryTransactionAttributeSourceAdvisorTransactionInterceptorTransactionAttributeSource到容器中

BeanFactoryTransactionAttributeSourceAdvisor:持有TransactionInterceptorTransactionAttributeSource。作为Advisor用于生成代理对象

AnnotationAwareAspectJAutoProxyCreator 根据Advisor定义的切面信息对目标bean进行代理

DataSourceTransactionManagerAutoConfiguration: 生成TransactionManager

源码分析

1. 注册Advisor

TransactionAutoConfiguration通过Import引入TransactionManagementConfigurationSelector

@AutoConfiguration(after = { JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@ConditionalOnClass(PlatformTransactionManager.class)
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnBean(TransactionManager.class)
    @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
    public static class EnableTransactionManagementConfiguration {

        @Configuration(proxyBeanMethods = false)
        //默认采用代理的方式,这种方式模式下,被代理类内部的本地调用不会走代理,意味着Spring事物管理不会介入
        @EnableTransactionManagement(proxyTargetClass = true)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
                matchIfMissing = true)
        public static class CglibAutoProxyConfiguration {

        }

    }
}

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
}

TransactionManagementConfigurationSelector引入两个类到Spring容器:AutoProxyRegistrarProxyTransactionManagementConfiguration

AutoProxyRegistrar负责生成代理对象的PostProcessor的注册,这个跟之前Spring AOP里的AnnotationAwareAspectJAutoProxyCreator都继承自AbstractAutoProxyCreator,如果Spring已经注册了AnnotationAwareAspectJAutoProxyCreator,则会避免后续AbstractAutoProxyCreator的子类的注册

ProxyTransactionManagementConfiguration负责生成拦截器

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { 
    @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;
        }
    }
}

ProxyTransactionManagementConfiguration注册用于事物管理的BeanFactoryTransactionAttributeSourceAdvisorSpring容器中,生成代理对象时注入该advisor

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);

        //为advisor设置事物拦截器,transactionInterceptor负责事物方法的自动事物管理
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        //主要负责事物注解里的属性解析,比如Transactional里的rollbackFor
        return new AnnotationTransactionAttributeSource();
    }

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

}

2. 生成代理对象

2.1 注册Creator

AutoProxyRegistrar注册InfrastructureAdvisorAutoProxyCreator到容器中


public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            if (mode == AdviceMode.PROXY) {
                    //注册InfrastructureAdvisorAutoProxyCreator
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
            }
    }
}

public abstract class AopConfigUtils {
    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }
}

AbstractAutoProxyCreatorpostProcessAfterInitialization负责生成代理对象

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //前面AOP的博文有分析过
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }
}

2.2 获取Advisor

这里跟aspect有一点小区别,因为事物对应的Advisor时已经被注册到Spring容器里的,所以是直接从Spring中获取。

public class BeanFactoryAdvisorRetrievalHelper {    
    public List<Advisor> findAdvisorBeans() {

        String[] advisorNames = this.cachedAdvisorBeanNames;
        if (advisorNames == null) {
            //从容器中获取实现了Advisor的Bean的Name
            //Spring 事物拦截器对应的name来自于下面这个常量
            //TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME
            advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this.beanFactory, Advisor.class, true, false);
            this.cachedAdvisorBeanNames = advisorNames;
        }
        if (advisorNames.length == 0) {
            return new ArrayList<>();
        }

        List<Advisor> advisors = new ArrayList<>();
        for (String name : advisorNames) {
                //根据beanName获取Bean
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
        }
        return advisors;
    }

初始化BeanFactoryTransactionAttributeSourceAdvisor时会默认初始化一个TransactionAttributeSourcePointcut作为该advisorPoint,该Point指向带Transactional注解的方法

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
        public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

                //初始化pointcut   
                private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {

                @Override
                public Pointcut getPointcut() {
                    return this.pointcut;
                }
        }
}

TransactionAttributeSourcePointcut会根据目标类里是否有Transactional注解来决定是否生成代理对象

private class TransactionAttributeSourceClassFilter implements ClassFilter {

        @Override
        public boolean matches(Class<?> clazz) {
            if (TransactionalProxy.class.isAssignableFrom(clazz) ||
                    TransactionManager.class.isAssignableFrom(clazz) ||
                    PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
                return false;
            }
            TransactionAttributeSource tas = getTransactionAttributeSource();
            //判断类里是否有Transactional注解
            return (tas == null || tas.isCandidateClass(clazz));
        }
}

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

    @Override
    public boolean isCandidateClass(Class<?> targetClass) {
        return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
    }
}

3. 事物管理

3.1 入口

TransactionAspectSupport#invokeWithinTransaction负责自动事物管理

    protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
            final InvocationCallback invocation) throws Throwable {

        TransactionAttributeSource tas = getTransactionAttributeSource();
        //通过判断method上是否有Transactional注解来决定method是否应该纳入Spring的自动事物管理
        //参考:SpringTransactionAnnotationParser#parseTransactionAnnotation
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

        //获取TransactionManager,默认从Spring容器中通过类型TransactionManager获取
        //如果method上的Transactional注解里指定了qualifier,则根据qualifier获取tm
        final TransactionManager tm = determineTransactionManager(txAttr);

        //响应式事物管理
        if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
            //....
        }

        PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

        if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
            // 开启事物,即设置autoCommit为false,mysql数据库即执行sql: SET autocommit=0,psql会执行Begin
            // 处理事物的传播性以及隔离级别
            // 事物开启参考:DataSourceTransactionManager#doBegin
            // psql参考:PgStatement#executeInternal。QueryExecutorImpl#sendQueryPreamble。QueryExecutorImpl#beginTransactionQuery
            // mysql参考: ConnectionImpl#setAutoCommit
            // psql隔离级别参考:PgConnection#setTransactionIsolation
            TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

            Object retVal;
            try {
                //如果还有拦截器的话,将请求传给下一个拦截器。否则调用目标方法
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // 如果抛出异常则回滚
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                //
                cleanupTransactionInfo(txInfo);
            }

            if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                // Set rollback-only in case of Vavr failure matching our rollback rules...
                TransactionStatus status = txInfo.getTransactionStatus();
                if (status != null && txAttr != null) {
                    retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                }
            }
            //提交事物
            commitTransactionAfterReturning(txInfo);
            return retVal;
        }
    }

3.2 事物传播行为

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
    @Override
    public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
            throws TransactionException {

        //拿到事物传播行为跟隔离级别
        TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

        //生成新的事物对象
        Object transaction = doGetTransaction();
        boolean debugEnabled = logger.isDebugEnabled();

        //当前方法是否已经处于事物中,通过transaction是否已持有数据库连接来判断
        if (isExistingTransaction(transaction)) {
            // 检查传播行为
            return handleExistingTransaction(def, transaction, debugEnabled);
        }

        // 如果当前方法不在事物中,同时传播行为又是PROPAGATION_MANDATORY
        if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }
        // 如果当前方法不在事物中,则在这些传播行为下开启一个新的事物
        else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
                def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {

            //开启一个新事物,把连接信息保存到transaction里
            return startTransaction(def, transaction, debugEnabled, suspendedResources);
        }
        else {
            // 到达这里当前方法不在已存在的事物中并且没有为当前方法创建新的事物
            // 能走到这里的传播级别只有PROPAGATION_NEVER、PROPAGATION_NOT_SUPPORTED、PROPAGATION_SUPPORTS
            ...
            return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
        }
    }
}

当前方法的调用者已处于事物中

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {  

    private TransactionStatus handleExistingTransaction(
            TransactionDefinition definition, Object transaction, boolean debugEnabled)
            throws TransactionException {

        //当前方法在事物中但传播行为是PROPAGATION_NEVER,则抛出异常
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
            throw new IllegalTransactionStateException(
                    "Existing transaction found for transaction marked with propagation 'never'");
        }

        //当前方法在事物中但传播行为是PROPAGATION_NOT_SUPPORTED
        //挂起当前事物,让当前方法在一个非事物的环境下运行
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {

            //挂起当前事物,主要目的是将上一个事物的连接信息从transaction对象里清空
            //以便在一个新的连接上以非事物的方式运行
            Object suspendedResources = suspend(transaction);
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return prepareTransactionStatus(
                    definition, null, false, newSynchronization, debugEnabled, suspendedResources);
        }

        //挂起当前事物并开启一个新事物
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
            //挂起当前事物,主要目的是将上一个事物的连接信息从transaction对象里清空
            //以便在一个新的连接上开启一个新的事物
            //startTransaction在发现transaction#connectionHolder为空时会去连接池获取一个新的空闲连接
            SuspendedResourcesHolder suspendedResources = suspend(transaction);
                return startTransaction(definition, transaction, debugEnabled, suspendedResources);
        }

        //在当前事物下创建一个savepoint,如果执行失败,则回滚到savepoing
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
            //非JTA事物管理下会使用savepoint来实现嵌套事物
            if (useSavepointForNestedTransaction()) {
                //创建新的事物状态信息,把当前事物的
                DefaultTransactionStatus status =
                        prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
                //创建savepoint。执行sql: SAVEPOINT `xx`
                //ConnectionImpl#setSavepoint
                status.createAndHoldSavepoint();
                return status;
            }
            else {
                //JTA下开启新事物。通过嵌套的begin commit
                return startTransaction(definition, transaction, debugEnabled, null);
            }
        }

        //PROPAGATION_SUPPORTS 跟 PROPAGATION_REQUIRED. 直接在当前事物下运行
}

相关文章

网友评论

      本文标题:Spring源码分析之事物管理

      本文链接:https://www.haomeiwen.com/subject/leictdtx.html