Spring事务的基本使用

注解方式

开启注解支持
  1. 在xml中开启注解方式支持
<!-- 开启注解方式的事务配置支持--
  <tx:annotation-driven transaction-manager="txManager"/>
  1. 或在java代码中以注解的方式(@EnableTransactionManagement)开启注解方式支持
使用
  1. 在要加事务管理的类或方法上加@Transactional注解
属性说明
public @interface Transactional {

//事务管理器
@AliasFor("transactionManager")
String value() default "";

@AliasFor("value")
String transactionManager() default "";

//传播行为
Propagation propagation() default Propagation.REQUIRED;

//隔离级别
Isolation isolation() default Isolation.DEFAULT;

//超时控制
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

//只读
boolean readOnly() default false;

//指定回滚异常
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};

//指定不回滚异常
Class<? extends Throwable>[] noRollbackFor() default {};	
String[] noRollbackForClassName() default {};

}

声明式

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
    init-method="init" destroy-method="close"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
    <!-- 配置初始化大小、最小、最大连接数 --> 
    <property name="initialSize" value="1" /> 
    <property name="minIdle" value="1" /> 
    <property name="maxActive" value="10" />
 </bean>
<!-- 配置事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- ********************** 声明式事务配置 begin   ************** -->
<!-- 配置事务增强的advice -->
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <!-- all methods starting with 'get' are read-only -->
        <tx:method name="get*" read-only="true" />
        <!-- other methods use the default transaction settings (see below) -->
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>

<!-- 配置事务的AOP切面 --> 
<aop:config>
    <aop:pointcut id="allService" expression="execution(* com.study.leesmall.spring.sample.tx.service.*Service.*(..)))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="allService"/>
</aop:config>
属性说明
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:attribute name="timeout" type="xsd:int" default="-1">

编程式

  1. Spring提供的最原始的事务管理方式是基于TransactionDefinitionPlatformTransactionManagerTransactionStatus 编程式事务。
  2. TransactionTemplate的编程式事务管理是使用模板方法设计模式对原始事务管理方式的封装。
//设置事务传播属性
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置事务的隔离级别,设置为读已提交(默认是ISOLATION_DEFAULT:使用的是底层数据库的默认的隔离级别)
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        // 设置是否只读,默认是false
        transactionTemplate.setReadOnly(true);
        // 默认使用的是数据库底层的默认的事务的超时时间
        transactionTemplate.setTimeout(30000);

Spring事务的传播机制

Spring事务底层是怎么工作的_回滚

Spring事务的隔离级别

  1. 首先要了解一下数据库的事务隔离级别

Spring事务底层是怎么工作的_隔离级别_02

  • RAED UNCOMMITED:读未提交,任何操作都不加锁,所以能读到其他事务修改但未提交的数据行,也称之为脏读(Dirty Read);
  • READ COMMITED:读操作不加锁,写操作加锁。读被加锁的数据时,读事务每次都读undo log中的最近版本,因此可能对同一数据读到不同的版本(不可重复读),但能保证每次都读到最新的数据(事务提交之后的,不可重复读,两次读不一致),但是不会在记录之间加间隙锁,所以允许新的记录插入到被锁定记录的附近,所以再多次使用查询语句时,可能得到不同的结果(Non-Repeatable Read);
  • REPEATABLE READ:第一次读数据的时候就将数据加行锁(共享锁),使其他事务不能修改当前数据,即可实现可重复读。但是不能锁住insert进来的新的数据,当前事务读取或者修改的同时,另一个事务还是可以insert提交,造成幻读
    (注:mysql的可重复读的隔离级别解决了 “不可重复读” 和 “幻读” 2个问题,因为使用了间隙锁,下文讲解)
  • SERIALIZABLE:InnoDB 锁表,读锁和写锁阻塞,强制事务串行执行,解决了幻读的问题;

总结:

  • 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大
  • 大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle
  • 少数数据库默认隔离级别为:Repeatable Read 如MySQL的InnoDB引擎(值得注意的是MySQL InnoDB引擎下的RR隔离级别已经通过next-key lock解决了幻读问题)

Spring事务的实现原理

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:

  1. 获取连接 Connection con = DriverManager.getConnection()
  2. 开启事务con.setAutoCommit(true/false);
  3. 执行CRUD
  4. 提交事务/回滚事务 con.commit() / con.rollback();
  5. 关闭连接 conn.close();

使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下:

编程式事务管理:

  1. 编程式事务管理使用TransactionTemplate可实现更细粒度的事务控制。

申明式事务管理:

  1. 配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
  2. spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。
  3. 真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

Spring事务的源码

编程式事务管理

Spring事务底层是怎么工作的_事务管理_03

查看TransactionTemplate类图

Spring事务底层是怎么工作的_Spring事务底层是怎么工作的_04

实现了TransactionOperations、InitializingBean这2个接口,进入看看具体有哪些方法

public interface TransactionOperations {

    /**
     * Execute the action specified by the given callback object within a transaction.
     * <p>Allows for returning a result object created within the transaction, that is,
     * a domain object or a collection of domain objects. A RuntimeException thrown
     * by the callback is treated as a fatal exception that enforces a rollback.
     * Such an exception gets propagated to the caller of the template.
     * @param action the callback object that specifies the transactional action
     * @return a result object returned by the callback, or {@code null} if none
     * @throws TransactionException in case of initialization, rollback, or system errors
     * @throws RuntimeException if thrown by the TransactionCallback
     */
    <T> T execute(TransactionCallback<T> action) throws TransactionException;

}
public interface InitializingBean {


/**
 * Invoked by a BeanFactory after it has set all bean properties supplied
 * (and satisfied BeanFactoryAware and ApplicationContextAware).
 * <p>This method allows the bean instance to perform initialization only
 * possible when all bean properties have been set and to throw an
 * exception in the event of misconfiguration.
 * @throws Exception in the event of misconfiguration (such
 * as failure to set an essential property) or if initialization fails.
 */
void afterPropertiesSet() throws Exception;


}

如,TransactionOperations这个接口用来执行事务的回调方法,InitializingBean是spring bean初始化流程中的,接下来看看具体的实现

@Override
    public void afterPropertiesSet() {
        if (this.transactionManager == null) {
            throw new IllegalArgumentException("Property 'transactionManager' is required");
        }
    }
@Override
public <T> T execute(TransactionCallback<T> action) throws TransactionException {       // 内部封装好的事务管理器
    if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
        return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
    }// 需要手动获取事务,执行方法,提交事务的管理器
    else {// 1.获取事务状态
        TransactionStatus status = this.transactionManager.getTransaction(this);
        T result;
        try {// 2.执行业务逻辑
            result = action.doInTransaction(status);
        }
        catch (RuntimeException ex) {
            // 应用运行时异常 -> 回滚
            rollbackOnException(status, ex);
            throw ex;
        }
        catch (Error err) {
            // Error异常 -> 回滚
            rollbackOnException(status, err);
            throw err;
        }
        catch (Throwable ex) {
            // 未知异常 -> 回滚
            rollbackOnException(status, ex);
            throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
        }// 3.事务提交
        this.transactionManager.commit(status);
        return result;
    }
}

如上所示,实际上afterPropertiesSet只是校验了事务管理器不为空,execute()才是核心方法,execute主要步骤:

  1. getTransaction()获取事务
  2. doInTransaction()执行业务逻辑,这里就是用户自定义的业务代码。如果是没有返回值的,就是doInTransactionWithoutResult()。
  3. commit()事务提交:调用AbstractPlatformTransactionManager的commit,rollbackOnException()异常回滚:调用AbstractPlatformTransactionManager的rollback(),事务提交回滚
申明式事务管理
  1. 使用代理模式,生成代理增强类。
  2. 根据代理事务管理配置类,配置事务的织入,在业务方法前后进行环绕增强,增加一些事务的相关操作。例如获取事务属性、提交事务、回滚事务。

Spring事务底层是怎么工作的_Spring事务底层是怎么工作的_05

看看@EnableTransactionManagement

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


//proxyTargetClass = false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
boolean proxyTargetClass() default false;

//事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
AdviceMode mode() default AdviceMode.PROXY;

//连接点上有多个通知时,排序,默认最低。值越大优先级越低。
int order() default Ordered.LOWEST_PRECEDENCE;
}

重点看类注解@Import(TransactionManagementConfigurationSelector.class)

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:
            // 向Spring中添加了AutoProxyRegistrar和ProxyTransactionManagementConfiguration对应的bean
            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);
   }

}

最终会执行selectImports方法导入需要加载的类,我们只看proxy模式下,载入了AutoProxyRegistrar、ProxyTransactionManagementConfiguration2个类。

  • AutoProxyRegistrar:给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
  • ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。

AutoProxyRegistrar

先看AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,复写registerBeanDefinitions方法,源码如下:

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
        for (String annoType : annoTypes) {
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
            if (candidate == null) {
                continue;
            }
            Object mode = candidate.get("mode");
            Object proxyTargetClass = candidate.get("proxyTargetClass");
            if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                    Boolean.class == proxyTargetClass.getClass()) {
                candidateFound = true;
                if (mode == AdviceMode.PROXY) {//代理模式
                    AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                    if ((Boolean) proxyTargetClass) {//如果是CGLOB子类代理模式
                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                        return;
                    }
                }
            }
        }
        if (!candidateFound) {
            String name = getClass().getSimpleName();
            logger.warn(String.format("%s was imported but no annotations were found " +
                    "having both 'mode' and 'proxyTargetClass' attributes of type " +
                    "AdviceMode and boolean respectively. This means that auto proxy " +
                    "creator registration and configuration may not have occurred as " +
                    "intended, and components may not be proxied as expected. Check to " +
                    "ensure that %s has been @Import'ed on the same class where these " +
                    "annotations are declared; otherwise remove the import of %s " +
                    "altogether.", name, name, name));
        }
    }

代理模式:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

最终调用的是:registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);基础构建增强自动代理构造器

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");       //如果当前注册器包含internalAutoProxyCreator
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {//org.springframework.aop.config.internalAutoProxyCreator内部自动代理构造器
            BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {//如果当前类不是internalAutoProxyCreator
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {//如果下标大于已存在的内部自动代理构造器,index越小,优先级越高,InfrastructureAdvisorAutoProxyCreator index=0,requiredPriority最小,不进入
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }
            return null;//直接返回
        }//如果当前注册器不包含internalAutoProxyCreator,则把当前类作为根定义
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);//优先级最高
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
    }

APC_PRIORITY_LIST列表如下:

/**
     * Stores the auto proxy creator classes in escalation order.
     */
    private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>();

    /**
     * 优先级上升list
     */
    static {
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }

由于InfrastructureAdvisorAutoProxyCreator这个类在list中第一个index=0,requiredPriority最小,不进入,所以没有重置beanClassName,啥都没做,返回null.

那么增强代理类何时生成呢?

InfrastructureAdvisorAutoProxyCreator类图如下:

Spring事务底层是怎么工作的_隔离级别_06

看2个核心方法:InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation实例化前+BeanPostProcessor接口的postProcessAfterInitialization初始化后

1     @Override
 2     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
 3         Object cacheKey = getCacheKey(beanClass, beanName);
 4 
 5         if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
 6             if (this.advisedBeans.containsKey(cacheKey)) {//如果已经存在直接返回
 7                 return null;
 8             }//是否基础构件(基础构建不需要代理):Advice、Pointcut、Advisor、AopInfrastructureBean这四类都算基础构建
 9             if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
10                 this.advisedBeans.put(cacheKey, Boolean.FALSE);//添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。
11                 return null;
12             }
13         }
14 
15         // TargetSource是spring aop预留给我们用户自定义实例化的接口,如果存在TargetSource就不会默认实例化,而是按照用户自定义的方式实例化,咱们没有定义,不进入
18         if (beanName != null) {
19             TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
20             if (targetSource != null) {
21                 this.targetSourcedBeans.add(beanName);
22                 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
23                 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
24                 this.proxyTypes.put(cacheKey, proxy.getClass());
25                 return proxy;
26             }
27         }
28 
29         return null;
30     }

通过追踪,由于InfrastructureAdvisorAutoProxyCreator是基础构建类,

advisedBeans.put(cacheKey, Boolean.FALSE)

添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。

我们再看postProcessAfterInitialization源码如下:

@Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {       // 如果是用户自定义获取实例,不需要增强处理,直接返回
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }// 查询map缓存,标记过false,不需要增强直接返回
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }// 判断一遍springAOP基础构建类,标记过false,不需要增强直接返回
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    
        // 获取增强List<Advisor> advisors
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);       // 如果存在增强
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);// 标记增强为TRUE,表示需要增强实现          // 生成增强代理类
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
     // 如果不存在增强,标记false,作为缓存,再次进入提高效率,第16行利用缓存先校验
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

下面看核心方法createProxy如下:

protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
     // 如果是ConfigurableListableBeanFactory接口(咱们DefaultListableBeanFactory就是该接口的实现类)则,暴露目标类
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {          //给beanFactory->beanDefinition定义一个属性:k=AutoProxyUtils.originalTargetClass,v=需要被代理的bean class
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
     //如果不是代理目标类
        if (!proxyFactory.isProxyTargetClass()) {//如果beanFactory定义了代理目标类(CGLIB)
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);//代理工厂设置代理目标类
            }
            else {//否则设置代理接口(JDK)
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
     //把拦截器包装成增强(通知)
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);//设置进代理工厂
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);//空方法,留给子类拓展用,典型的spring的风格,喜欢处处留后路
     //用于控制代理工厂是否还允许再次添加通知,默认为false(表示不允许)
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {//默认false,上面已经前置过滤了匹配的增强Advisor
            proxyFactory.setPreFiltered(true);
        }
        //代理工厂获取代理对象的核心方法
        return proxyFactory.getProxy(getProxyClassLoader());
    }

最终我们生成的是CGLIB代理类.到此为止我们分析完了代理类的构造过程。

ProxyTransactionManagementConfiguration

下面来看ProxyTransactionManagementConfiguration:

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)//定义事务增强器
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor j = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource());
        advisor.setAdvice(transactionInterceptor());
        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;
    }

}

核心方法:transactionAdvisor()事务织入

定义了一个advisor,设置事务属性、设置事务拦截器TransactionInterceptor、设置顺序。核心就是事务拦截器TransactionInterceptor。

TransactionInterceptor使用通用的spring事务基础架构实现“声明式事务”,继承自TransactionAspectSupport类(该类包含与Spring的底层事务API的集成),实现了MethodInterceptor接口

Spring事务底层是怎么工作的_Spring事务底层是怎么工作的_07

事务拦截器的拦截功能就是依靠实现了MethodInterceptor接口,熟悉spring的同学肯定很熟悉MethodInterceptor了,这个是spring的方法拦截器,主要看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);

        // 调用TransactionAspectSupport的 invokeWithinTransaction方法
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

TransactionInterceptor复写MethodInterceptor接口的invoke方法,并在invoke方法中调用了父类TransactionAspectSupport的invokeWithinTransaction()方法,源码如下:

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

        // 如果transaction attribute为空,该方法就是非事务(非编程式事务)
        final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        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 {
                // 这里就是一个环绕增强,在这个proceed前后可以自己定义增强实现
                // 方法执行
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // 根据事务定义的,该异常需要回滚就回滚,否则提交事务
                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,
                        new TransactionCallback<Object>() {
                            @Override
                            public Object doInTransaction(TransactionStatus status) {
                                TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                                try {
                                    return invocation.proceedWithInvocation();
                                }
                                catch (Throwable ex) {// 如果该异常需要回滚
                                    if (txAttr.rollbackOn(ex)) {
                                        // 如果是运行时异常返回
                                        if (ex instanceof RuntimeException) {
                                            throw (RuntimeException) ex;
                                        }// 如果是其它异常都抛ThrowableHolderException
                                        else {
                                            throw new ThrowableHolderException(ex);
                                        }
                                    }// 如果不需要回滚
                                    else {
                                        // 定义异常,最终就直接提交事务了
                                        throwableHolder.throwable = ex;
                                        return null;
                                    }
                                }
                                finally {//清空当前事务信息,重置为老的
                                    cleanupTransactionInfo(txInfo);
                                }
                            }
                        });
    
                // 上抛异常
                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;
            }
        }
    }

我们主要看第一个分支,申明式事务,核心流程如下:

1.createTransactionIfNecessary():如果有必要,创建事务

protected TransactionInfo createTransactionIfNecessary(
            PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {

        // 如果还没有定义名字,把连接点的ID定义成事务的名称
        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);
    }

2.InvocationCallback的proceedWithInvocation():InvocationCallback是父类的内部回调接口,子类中实现该接口供父类调用,子类TransactionInterceptor中invocation.proceed()。回调方法执行

3.异常回滚completeTransactionAfterThrowing()

事务管理器的PlatformTransactionManager

Spring事务底层是怎么工作的_隔离级别_08

public interface PlatformTransactionManager {
    // 获取事务状态
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
  // 事务提交
    void commit(TransactionStatus status) throws TransactionException;
  // 事务回滚
    void rollback(TransactionStatus status) throws TransactionException;
}
  1. getTransaction 获取事务

Spring事务底层是怎么工作的_事务管理_09

  1. commit 事务提交

Spring事务底层是怎么工作的_隔离级别_10

  1. rollback 事务回滚

Spring事务底层是怎么工作的_Spring事务底层是怎么工作的_11

整体流程

Spring事务底层是怎么工作的_事务管理_12