Spring 中使用事务,以及它的底层原理
spring中几种事务的实现方式?
1.编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。(已经不用了)
<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 便可。
关于事务管理器,springBoot默认会帮我注入一个事务管理器,但是当我们添加的持久化依赖比较多,我们还是会选择人为的指定使用哪个事务管理器。 我们可以人为创建多个事务管理器,但是在@Transactional里面需要显式给定value属性
https://www.cnblogs.com/xingzc/p/6029483.html
@Transactional加在类上面和方法上面有什么区别?
然后在Service中,被 @Transactional 注解的方法,将支持事务。如果注解在类上,则整个类的所有方法都默认支持事务。
如果你在方法上定义的话,方法的@Transactional会覆盖类上面声明的事务。
spring中的事务传播行为:Propagation这个属性(7种)
REQUIRED:required(Spring默认的传播机制是这一个)
1.在外围方法未开启事务的情况下Propagation.REQUIRED
修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰
2.外围方法开启事务的情况下Propagation.REQUIRED
修饰的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED
修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。(共为一个事务)
REQUIRES_NEW:requires_new
1.在外围方法未开启事务的情况下Propagation.REQUIRES_NEW
修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
2.在外围方法开启事务的情况下Propagation.REQUIRES_NEW
修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。(完全相互独立)
NESTED:nested
1.在外围方法未开启事务的情况下Propagation.NESTED
和Propagation.REQUIRED
作用相同,修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。
2.在外围方法开启事务的情况下Propagation.NESTED
修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务。(外部回滚,内部一定回滚;内部回滚不影响外部)
PROPAGATION_SUPPORT:支持当前事务,如果当前没有事务,就不以事务方式运行。
PROPAGATION_MANDATORY:一定要在事务中运行,调用此方法必须原先就有一个事务,否则运行时抛异常。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果之前有事务,将之前事务挂起,此方法内无事务执行。
PROPAGATION_NEVER:以非事务方式执行,如果之前有事务就抛异常。
https://segmentfault.com/a/1190000013341344
Spring中事务的底层原理:
还是借助AOP中动态代理的思想,借助方法拦截器(MethodInterceptor),这里应该是用的cglib代理,在加入事务处理的方法上额外加一些操作。
到这里,大致介绍完Spring是如何进行事务了,其实现原理源自与自定义标签,而开启自定义标签之后会注册三个关于Advisor的Bean(AnnotationTransactionAttributeSource类型的Bean,TransactionInterceptor类型的Bean,BeanFactoryTransactionAttributeSourceAdvisor类型的Bean),和一个BeanPostProssor
,当Spring中有BeanPostProssor
时,会在每个Bean实例化与依赖注入之后执行BeanPostProssor
的postProcessAfterInitialization方法,在这个方法中,会对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
代表一个事务运行的状态,事务管理器通过状态可以知道事务的状态信息,然后进行事务的控制。事务是否完成,是否是新的事务,是不是只能回滚等。
参考:
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10616790.html