1.编程式事务管理对基于 POJO 的应用来讲是惟一选择。咱们须要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。(已经不用了)html
<aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean>
springBoot 使用事务很是简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,而后在访问数据库的Service方法上添加注解 @Transactional 即可。java
关于事务管理器,springBoot默认会帮我注入一个事务管理器,可是当咱们添加的持久化依赖比较多,咱们仍是会选择人为的指定使用哪一个事务管理器。 咱们能够人为建立多个事务管理器,可是在@Transactional里面须要显式给定value属性spring
http://www.javashuo.com/article/p-aprrydaz-bt.html数据库
而后在Service中,被 @Transactional 注解的方法,将支持事务。若是注解在类上,则整个类的全部方法都默认支持事务。编程
若是你在方法上定义的话,方法的@Transactional会覆盖类上面声明的事务。segmentfault
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.NESTED
和Propagation.REQUIRED
做用相同,修饰的内部方法都会新开启本身的事务,且开启的事务相互独立,互不干扰。
2.在外围方法开启事务的状况下Propagation.NESTED
修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务必定回滚,而内部子事务能够单独回滚而不影响外围主事务和其余子事务。(外部回滚,内部必定回滚;内部回滚不影响外部)
PROPAGATION_SUPPORT:支持当前事务,若是当前没有事务,就不以事务方式运行。
PROPAGATION_MANDATORY:必定要在事务中运行,调用此方法必须原先就有一个事务,不然运行时抛异常。
PROPAGATION_NOT_SUPPORTED:以非事务方式执行,若是以前有事务,将以前事务挂起,此方法内无事务执行。
PROPAGATION_NEVER:以非事务方式执行,若是以前有事务就抛异常。
http://www.javashuo.com/article/p-qqonfnlw-bd.html
仍是借助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
表明一个事务运行的状态,事务管理器经过状态能够知道事务的状态信息,而后进行事务的控制。事务是否完成,是不是新的事务,是否是只能回滚等。
参考: