Spring 中使用事务,以及它的底层原理

spring中几种事务的实现方式?

1.编程式事务管理对基于 POJO 的应用来讲是惟一选择。咱们须要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。(已经不用了)html

2.基于 TransactionProxyFactoryBean的声明式事务管理
3.基于 @Transactional 的声明式事务管理
4.基于Aspectj AOP配置事务,其实是cjlib动态代理
<aop:aspectj-autoproxy proxy-target-class="true" /> 
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean>

spring boot如何使用事务?

 springBoot 使用事务很是简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,而后在访问数据库的Service方法上添加注解 @Transactional 即可。java

关于事务管理器,springBoot默认会帮我注入一个事务管理器,可是当咱们添加的持久化依赖比较多,咱们仍是会选择人为的指定使用哪一个事务管理器。 咱们能够人为建立多个事务管理器,可是在@Transactional里面须要显式给定value属性spring

http://www.javashuo.com/article/p-aprrydaz-bt.html数据库

@Transactional加在类上面和方法上面有什么区别?

而后在Service中,被 @Transactional 注解的方法,将支持事务。若是注解在类上,则整个类的全部方法都默认支持事务。编程

若是你在方法上定义的话,方法的@Transactional会覆盖类上面声明的事务。segmentfault

spring中的事务传播行为:Propagation这个属性(7种)

REQUIRED:required(Spring默认的传播机制是这一个)post

1.在外围方法未开启事务的状况下Propagation.REQUIRED修饰的内部方法会新开启本身的事务,且开启的事务相互独立,互不干扰ui

2.外围方法开启事务的状况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,全部Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。(共为一个事务)spa

REQUIRES_NEW:requires_new线程

1.在外围方法未开启事务的状况下Propagation.REQUIRES_NEW修饰的内部方法会新开启本身的事务,且开启的事务相互独立,互不干扰。

2.在外围方法开启事务的状况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。(彻底相互独立)

NESTED:nested

1.在外围方法未开启事务的状况下Propagation.NESTEDPropagation.REQUIRED做用相同,修饰的内部方法都会新开启本身的事务,且开启的事务相互独立,互不干扰。

2.在外围方法开启事务的状况下Propagation.NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务必定回滚,而内部子事务能够单独回滚而不影响外围主事务和其余子事务。(外部回滚,内部必定回滚;内部回滚不影响外部)

PROPAGATION_SUPPORT:支持当前事务,若是当前没有事务,就不以事务方式运行。

PROPAGATION_MANDATORY:必定要在事务中运行,调用此方法必须原先就有一个事务,不然运行时抛异常。

PROPAGATION_NOT_SUPPORTED:以非事务方式执行,若是以前有事务,将以前事务挂起,此方法内无事务执行。

PROPAGATION_NEVER:以非事务方式执行,若是以前有事务就抛异常。

http://www.javashuo.com/article/p-qqonfnlw-bd.html

Spring中事务的底层原理:

仍是借助AOP中动态代理的思想,借助方法拦截器(MethodInterceptor),这里应该是用的cglib代理,在加入事务处理的方法上额外加一些操做。

 

到这里,大体介绍完Spring是如何进行事务了,其实现原理源自与自定义标签,而开启自定义标签以后会注册三个关于Advisor的Bean(AnnotationTransactionAttributeSource类型的Bean,TransactionInterceptor类型的Bean,BeanFactoryTransactionAttributeSourceAdvisor类型的Bean),和一个BeanPostProssor,当Spring中有BeanPostProssor时,会在每一个Bean实例化与依赖注入以后执行BeanPostProssorpostProcessAfterInitialization方法,在这个方法中,会对Bean进行验证是否须要进行代理,若是须要则将上面的Advisor与此Bean一块儿去交给动态代理工厂作一个代理,返回代理类给IOC容器,若是不须要进行代理直接返回原Bean,达到了事务的效果。Advisor中的advice是事务功能实现的关键类,也就是自定义标签注册的Bean中叫作TransactionInterceptor的这个类。

TransactionInterceptor中的invoke方法中会执行:

@Nullable
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);
    // 从属性中获取事务管理器,这里承接上一篇文章中自定义标签那里,在配置文件中配置一个事务管理器
    // PlatformTransactionManager有不少种,这里分析经常使用的DataSourceTransactionManager
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    // 给pointcut一个名称
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
 
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // 这里执行声明式事务// 建立一个带有事务信息的对象TransactionInfo,这个对象是能够获取事务管理器的,进而经过事务管理器再执行回滚啊,提交啊这些方法
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
        Object retVal = null;
        try {// 执行原方法
            retVal = invocation.proceedWithInvocation();
        }
        catch (Throwable ex) {// 若是有异常就走这里,对异常进行处理
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {
            // 若是Info里存在旧的Info,将旧的Info放入当前线程表示将当前Info变为上一个Info
            cleanupTransactionInfo(txInfo);
        }
        // 若是程序没有发生异常,就会走到这里,执行提交的操做
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }
 
    else {
        // 这里执行编程式事务 本文只讨论声明式事务
        // 略....
    }
}

事务底层原理讲的很是好:

https://www.javazhiyin.com/24920.html

https://www.javazhiyin.com/24922.html

事务拦截的对象:TransactionInterceptor

 

Spring事务中的关键对象:

PlatformTransactionManager 事务管理器

  包含获取事务,提交事务,回滚事务三个方法

  getTransaction(TransactionDefinition)

  commit(TransactionStatus)

  roollback(TransactionStatus)

TransactionDefiition

  定义事务的类型,事务包含不少属性,是否可读,事务隔离级别,事务传播级别。经过事务的定义,咱们根据定义获取特定的事务。

TransactionStatus

  表明一个事务运行的状态,事务管理器经过状态能够知道事务的状态信息,而后进行事务的控制。事务是否完成,是不是新的事务,是否是只能回滚等。

 

参考:

https://www.jianshu.com/p/ecf55d6f0118

https://zhuanlan.zhihu.com/p/54067384

相关文章
相关标签/搜索