博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码(5) - Spring事务入门与源码分析
阅读量:4166 次
发布时间:2019-05-26

本文共 10332 字,大约阅读时间需要 34 分钟。

Spring-事务

什么是事务?

      事务就是完成一件事情所要完成的N个任务,但是如果其中一个任务失败了,可能就导致这件事情就失败了。比如吃饭,吃饭之前要先拿碗筷、洗碗筷、摆放好碗筷,如果在拿碗筷的过程中把碗给摔了,那么就吃不成饭了。

 

事务分类

      编程式事务:TransactinTemplate或者使用底层的PlatformTransactionManager事务管理器来手动开启、提交、关闭事务。

      声明式事务:建立在Aop的基础上,使用@Transactional注解或xml配置方式,对目标方法进行拦截式事务处理。

 

事务特性

      原子性(Atomicity):强调事务的不可分割性,数据的原始不会出现给“串”改。

      一致性(Consistency):事务执行前后数据的完整性保持一致。

      隔离性(Isolation):一个事务执行过程中,不应该受到其他事务的干扰。

      持久性(Durability):事务一旦结束,数据就持久化的保持在数据库中。

 

事务隔离级别

事务并发的问题

      脏读(Dirty Read):A事务执行过程中,B事务读取了A事务的修改。但A事务在还没有提交的情况下,发生了回滚操作。则B事务所读取的数据就会不正常了。这个未提交的数据就是脏读。

      不可重复读(Norepeatable Read):A事务和B事务同时对数据1进行访问,A事务对数据1进行读取,B事务对数据1进行修改。A事务第一次读取到数据1时,是123。第二次去读取时,是321。这个321是B事务修改的数据。即A第一次读取时,B事务还没有提交。第二次读取时,B事务已经提交了,读取到的是B事务的数据,所以就出现了两次读取的数据不一样。还有一种情况就是A事务和B事务,同时更新数据1,后更新的事务,会导致先更新的数据的数据丢失。

      幻读(Phantom Read):表1只有一条数据,A事务对表1进行数据读取,只读取到了一条数据。同时事务B对表1新增了一条数据。所以其实表中是有2条数据的,就像出现了幻觉一样。

      序列(Serializable):保证上面的所有情况都不会发生。

 

事务隔离级别

      Read_UnCommitted(读未提交):可读取未提交事务的操作,这种情况会出现脏读、不可重复读、幻读。但是并发性能高。

      Read_Commited(读提交):事务A等待事务B提交之后才可以进行读取,解决了脏读的问题,即锁定正在读取的行,但是会出现重复读、幻读的问题。

      Repeatable_Read(重复读):读取事务开启的时候不能对数据进行修改,即锁定读取的所有行。但是会出现幻读。

      Serializable(序列化):最高的事务隔离级别,在该级别下,事务串行化顺序执行,即锁表。可以避免脏读、不可重复度、幻读。但是这种事务的效率低,比较耗数据库性能,一般不使用。

 

事务传播级别(7种)

      Required(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务。即A有事务则B加入A事务,如果A没有事务,则创建一个B事务。

      Propagation_Required_New创建一个新事务,如果当前事务存在,把当前事务挂起。即B总是开启一个新事务,如果A有事务则把A事务挂起先执行B事务。

      Propagation_Nested嵌套事务,如果但事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟Required一样。即如果A没有事务则新建一个事务,如果A有事务则把B的事物当成A的一个子事务,A事务rollback,commit影响B,B事务rollback,commit不影响A。

      Propagation_Supports支持使用当前事务,如果当前事务不存在,则不使用事务。如果A没有事务,那就按普通方法执行,如果有A事务则用A的事务,( B本身不具备事务)。

      Propagation_Not_Supported无事务执行,如果当前事务存在,把当前事务挂起。即B总是非事务的执行,如果A有事务则把A事务挂起,自己还是以普通方法执行(B本身不具备事务)。

      Propagation_Never无事务执行,如果当前有事务则抛出Exception。即如果A没事务,那就按普通方法执行,如果A有事务则抛出异常(B本身不具备事务)。

      Propagation_Mandatory翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。即A没有事务就抛异常,如果A有事务则使用A的事物(B本身不具备事务)。

 

源码分析

@EnableTransactionManagement:入口

156行:@Import(TransactionManagementConfigurationSelector.class),可以看到这个类

 

进入:TransactionManagementConfigurationSelector:

47行:return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};

 

进入AutoProxyRegistrar:

72行:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);,注册代理类

 

进入:AopConfigUtils - registerAutoProxyCreatorIfNecessary:

72行:return registerAutoProxyCreatorIfNecessary(registry, null);

79行:注册InfrastructureAdvisorAutoProxyCreator这个类

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

 

进入InfrastructureAdvisorAutoProxyCreator:

InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator

 --> class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator

   --> class AbstractAutoProxyCreator extends ProxyProcessorSupport

            implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

      --> interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor

 

InfrastructureAdvisorAutoProxyCreator小结

在InfrastructureAdvisorAutoProxyCreator中可以看到,其实是继承了SmartInstantiationAwareBeanPostProcessor。可以看到熟悉的postProcessBeforeInstantiation和postProcessAfterInstantiation的前后置方法。

即利用后置处理器机制在创建以后,包装对象,返回一个代理对象(增强),代理对象执行方法时,利用拦截器链进行调用。

 

回到TransactionManagementConfigurationSelector:

47行:return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};

 

进入ProxyTransactionManagementConfiguration(事务管理配置类):

42行:transactionAdvisor(),事务属性源的相关增强

44行:advisor.setTransactionAttributeSource(transactionAttributeSource());,设置事务属性源

55行:进入transactionAttributeSource()方法,return new AnnotationTransactionAttributeSource();,返回了AnnotationTransactionAttributeSource这个类。

 

点进去55行的AnnotationTransactionAttributeSource看下。

 

进入AnnotationTransactionAttributeSource:

74行:

public AnnotationTransactionAttributeSource() {

    this(true);

}

87行:

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {

    this.publicMethodsOnly = publicMethodsOnly;

    this.annotationParsers = new LinkedHashSet<>(2);

   

    //Spring事务解析

    this.annotationParsers.add(new SpringTransactionAnnotationParser());

   

    //jta解析

    if (jta12Present) {

         this.annotationParsers.add(new JtaTransactionAnnotationParser());

    }

   

    //ejb3解析

    if (ejb3Present) {

         this.annotationParsers.add(new Ejb3TransactionAnnotationParser());

    }

}

 

90行:this.annotationParsers.add(new SpringTransactionAnnotationParser());,Spring的事物注解解析

 

进入SpringTransactionAnnotationParser:

58行:parseTransactionAnnotation(),解析事务注解属性。这个方法的内容从@Transactional的注解源码中可以找到。如rollbackForClassName。

 

AnnotationTransactionAttributeSource小结

事务增强器要用事务注解的信息,使用这个类解析事务注解。

 

回到ProxyTransactionManagementConfiguration - transactionAdvisor():

44行:已经解析了注解事务的解析问题了。

45行:advisor.setAdvice(transactionInterceptor());,目标通知方法

60行:进入transactionInterceptor()方法

public TransactionInterceptor transactionInterceptor() {

    //事务拦截器,如同AOP时,@Before对应BeforeInterceptor,现在@Transactional对应TransactionInterceptor

    TransactionInterceptor interceptor = new TransactionInterceptor();

   

    //事务属性解析

    interceptor.setTransactionAttributeSource(transactionAttributeSource());

   

    if (this.txManager != null) {

         //设置事务管理器

         interceptor.setTransactionManager(this.txManager);

    }

    return interceptor;

}

 

进入TransactionInterceptor:

52行:class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable,实现了MethodInterceptor,和之前的AOP源码解析很像。

当执行目标方法时:

            执行拦截器链

            事务拦截器

1、获取事务相关属性

2、获取PlatformTransactionManager事务管理器,通过事务管理器去执行目标方法。

 

91行:invoke(final MethodInvocation invocation),代理调用方法

98行:return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);,可以看到invokeWithinTransaction()这个方法是调用父类TransactionAspectSupport(事务切面支持类)。

 

事务拦截链

进入TransactionAspectSupport - invokeWithinTransaction():

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,

         final InvocationCallback invocation) throws Throwable {

 

    //获取事务属性源

    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);

   

    //如果@Transactional注解的属性没有配置,那么则进入

    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {

         // Standard transaction demarcation with getTransaction and commit/rollback calls.

        

         //获取事务信息,如果有必须要对这个方法进行拦截  ▲▲▲ 进入createTransactionIfNecessary()方法

         TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

         Object retVal = null;

         try {

             //调用目标方法,但是如果是下一个是拦截链的下一个方法则会先调用拦截链对应的方法在调用目标方法

             retVal = invocation.proceedWithInvocation();

         }

         catch (Throwable ex) {

             //如果报错了,那么则回滚这个方法 ▲▲▲ 进入completeTransactionAfterThrowing()方法

             completeTransactionAfterThrowing(txInfo, ex);

             throw ex;

         }

         finally {

             //清理这个事务信息 ▲▲▲ 进入cleanupTransactionInfo()方法

             cleanupTransactionInfo(txInfo);

         }

        

         //最后把这个确定了的状态给提交上去

         commitTransactionAfterReturning(txInfo);

         return retVal;

    }

 

    //如果@Transactional有带属性过来的,那么则还要解析这个属性规则,根据这个规则去做一个逻辑执行,其他逻辑如上

    else {

         final ThrowableHolder throwableHolder = new ThrowableHolder();

 

         try {

             Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {

                  TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);

                 

                  ......

                 

             });

 

             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;

         }

    }

}

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,

         @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

 

    //如果没有名称,则表示为方法名称

    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);

}

protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,

         @Nullable TransactionAttribute txAttr, String joinpointIdentification,

         @Nullable TransactionStatus status) {

 

    TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);

    if (txAttr != null) {

         if (logger.isTraceEnabled()) {

             logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");

         }

         //已经存在的,则标记为不兼容

         txInfo.newTransactionStatus(status);

    }

    else {

         //保持维护的ThreadLoacal的完整性

         if (logger.isTraceEnabled())

             logger.trace("Don't need to create transaction for [" + joinpointIdentification +

                      "]: This method isn't transactional.");

    }

 

    //绑定到线程,保证TransactionInfo被正确的管理,▲▲▲ 进入bindToThread()方法

    txInfo.bindToThread();

    return txInfo;

}

private void bindToThread() {

    //先保存这个事务的状态下来

    this.oldTransactionInfo = transactionInfoHolder.get();

    transactionInfoHolder.set(this);

}

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {

    if (txInfo != null && txInfo.getTransactionStatus() != null) {

         ....

        

         //回滚

         txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());

        

         //提交这个新状态

         txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

        

         ....

    }

}

protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {

    if (txInfo != null) {

         //重置这个线程的状态

         txInfo.restoreThreadLocalStatus();

    }

}

 

Spring事务源码总结

1、@EnableTransactionManagement > TransactionManagementConfigurationSelector > 注册代理类 > 利用后置处理器包装对象返回代理类

2、AnnotationTransactionAttributeSource > 事务配置信息 > SpringTransactionAnnotationParser > 配置信息解析 > 设置事务管理器

3、TransactionAspectSupport > 建立事务拦截链 > invokeWithinTransaction > 执行目标方法 > 根据执行结果决定是否回滚

 

转载地址:http://uqmxi.baihongyu.com/

你可能感兴趣的文章
springmvc传值
查看>>
在Eclipse中查看Android源码
查看>>
[转]C语言printf
查看>>
对话周鸿袆:从程序员创业谈起
查看>>
Mysql中下划线问题
查看>>
Xcode 11 报错,提示libstdc++.6 缺失,解决方案
查看>>
vue项目打包后无法运行报错空白页面
查看>>
1136 . 欧拉函数
查看>>
面试题:强制类型转换
查看>>
Decorator模式
查看>>
Template模式
查看>>
Observer模式
查看>>
高性能服务器设计
查看>>
图文介绍openLDAP在windows上的安装配置
查看>>
Pentaho BI开源报表系统
查看>>
Pentaho 开发: 在eclipse中构建Pentaho BI Server工程
查看>>
JSP的内置对象及方法
查看>>
android中SharedPreferences的简单例子
查看>>
android中使用TextView来显示某个网址的内容,使用<ScrollView>来生成下拉列表框
查看>>
andorid里关于wifi的分析
查看>>