一、简介接着上篇 数据库事务简介,来聊聊 Spring 事务 。
Spring 本身并不实现事务,Spring 事务的本质还是底层数据库对事务的支持,没有数据库事务的支持,Spring 事务就不会生效 。
Spring 事务提供了一套抽象的事务管理,并且结合 Spring IOC 和 Spring AOP,简化了应用程序使用数据库事务,并且通过声明式事务,可以做到应用程序无侵入的事务功能 。例如使用 JDBC 操作数据库,想要使用事务的步骤为:
- 获取连接 Connection conn= DriverManager.getConnection()
- 开启事务 conn.setAutoCommit(true/false);
- 执行 CRUD
- 提交事务/回滚事务 conn.commit() / conn.rollback();
- 关闭连接 conn.close();
Spring 事务的本质其实就是 AOP 和 数据库事务,Spring 将数据库的事务操作提取为切面,通过 AOP 的方式增强事务方法 。
二、Spring 事务传播行为PROPAGATION_REQUIRED:默认,如果当前没有事务,就新建一个事务;如果当前存在事务,加入到这个事务中 。
PROPAGATION_SUPPORTS:如果当前没有事务,那么就以非事务的形式执行;如果当前存在事务,加入到这个事务中 。
PROPAGATION_MANDATORY:必须在一个事务中执行 。如果当前没有事务,则抛出异常;如果当前存在事务,加入到这个事务中 。
PROPAGATION_REQUIRES_NEW:如果当前没有事务,就新建一个事务;如果当前存在事务,就把当前事务挂起,新建一个事务 。
PROPAGATION_NOT_SUPPORTED:当前不支持事务 。如果当前没有事务,那么就以非事务的形式执行;如果当前存在事务,就把当前事务挂起,以非事务的形式执行 。
PROPAGATION_NEVER:不能在事务中执行 。如果当前没有事务,那么就以非事务的形式执行;如果当前存在事务,则抛出异常 。
PROPAGATION_NESTED:如果当前没有事务,就新建一个事务;如果当前存在事务,则在嵌套事务内执行 。
三、使用 Spring 事务1. 通过 PlatformTransactionManager使用(不推荐)
@org.junit.Testpublic void test1() {// 默认的事务定义DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();PlatformTransactionManager transactionManager = SpringUtils.getBean(PlatformTransactionManager.class);// 开启事务TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);try {// do something} catch (Exception e) {// 事务回滚transactionManager.rollback(transactionStatus);}// 事务提交transactionManager.commit(transactionStatus);}2. 通过 TransactionTemplate 使用事务@org.junit.Testpublic void test2() {PlatformTransactionManager transactionManager = SpringUtils.getBean(PlatformTransactionManager.class);TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);Boolean execute = transactionTemplate.execute(transactionStatus -> {// do somethingreturn Boolean.TRUE;});}3. 声明式事务我们经常使用的基于 XML 配置或者注解的方式使用的事务方式 。@Transactional(rollbackFor = Exception.class)public OrderDealResultDTO createOrder(OrderCreateParam orderCreateParam) { xxx }四、实现原理我们知道实现 @Transactional 原理是基于 Spring Aop,Spring 为我们定义了以 @Transactional 注解为植入点的切点,类似于@Around 。1. Spring 中的 Advisor,Advice,Point 概述Advice:用于定义拦截行为,祖先接口为
org.aopalliance.aop.Advice,该接口只是标识接口,应用中可直接实现 BeforeAdvice、ThrowsAdvice、MethodInterceptor、AfterReturningAdvice、IntroductionInterceptor 等子接口 。Pointcut:用于定义拦截目标集合,祖先接口为
org.springframework.aop.Pointcut 。Advisor:是 Spring AOP 的顶层抽象,充当 Advice 和 Pointcut 的适配器,一般有 advice 和 pointcut 属性 。祖先接口为
org.springframework.aop.Advisor,应用中可直接使用 org.springframework.aop.support.DefaultPointcutAdvisor 。2. BeanFactoryTransactionAttributeSourceAdvisorSpring 会在 IOC 容器创建一个 BeanFactoryTransactionAttributeSourceAdvisor 实例,这个实例可以看作是一个切点,在判断一个 bean 在初始化过程中是否需要创建代理对象,都需要验证一次 BeanFactoryTransactionAttributeSourceAdvisor 是否是适用这个 Bean 的切点 。如果是,就需要创建代理对象,并且把 BeanFactoryTransactionAttributeSourceAdvisor 实例注入到代理对象中 。
Spring 事务把整个事务流程模板化,采用 AOP 的形式增强到需要事务的方法,
BeanFactoryTransactionAttributeSourceAdvisor 就是 Spring 事务的增强方法,其中 Ponintcut 是 TransactionAttributeSourcePointcut,Advice 是 TransactionInterceptor 。 @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());if (this.enableTx != null) {advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor; }因此,调用 Spring 事务方法,就委托给了 TransactionInterceptor 的 invoke 方法 。 @Override @Nullable public Object invoke(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);// Adapt to TransactionAspectSupport's invokeWithinTransaction...// Spring 事务处理逻辑return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
文章插图
3. PlatformTransactionManagerPlatformTransactionManager 是 Spring 事务结构中的核心接口,Spring 并不直接管理事务,而是提供了多种事务管理器(JDBC、Hibernate、JTA 等),然后将事务管理的职责委托给这些事务管理器 。

文章插图
- TransactionDefinition:事务定义对象,封装了 @Transactional 注解中设置的各种信息;
- TransactionStatus:表示一个事务状态,在应用程序中可以通过 TransactionInterceptor.currentTransactionStatus() 的静态函数获取到;
- TransactionInfo:事务信息对象,包括一个事务所有的信息,包括事务管理器、事务定义对象、事务状态对象、目标方法唯一标识等等;
@Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,final InvocationCallback invocation) throws Throwable {// 1. 准备事务的基本信息// If the transaction attribute is null, the method is non-transactional.TransactionAttributeSource tas = getTransactionAttributeSource();// 事务定义 TransactionAttribute 是 TransationDefinition 的子类final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);// 获取事务管理器,根据事务定义指定的事务管理器获取到指定的事务管理器 。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.// 2. 开启事务// 如果必要才会开启事务,这里会根据事务的传播能力信息来决定是否开启事务还是加入到一个已经存在的事务,这里会涉及到事务的挂起TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal = null;try {// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.// 执行目标方法或者执行 AOP 拦截链中的下一个拦截器retVal = invocation.proceedWithInvocation();}catch (Throwable ex) {// target invocation exception// 3. 事务的回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;}finally {// 清理事务信息cleanupTransactionInfo(txInfo);}// 4. 提交事务commitTransactionAfterReturning(txInfo);return retVal;}// 省略下文}5. 其它- TransationSynchronization:事务同步回调接口,在事务的各个点执行回调方法,比如挂起、继续、提交前后,完成前后等 。在 Spring-Mybatis 整合时,Mybatis 正是利用了 TransationSynchronization 同步器,才让 Mybatis 的事务管理交给了 Spring 事务来管理 。
- TransactionSynchronizationManager:事务同步回调接口的管理器,用来管理当前线程的事务,常用在事务执行点实现自己的一些逻辑,因此 TransactionSynchronizationManager 保存着事务运行过程中的一些状态,比如数据库连接等;
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void beforeCommit(boolean readOnly) {// do something}@Overridepublic void afterCommit() {// do something}});- SuspendedResourcesHolder:用来记录挂起事务的运行时信息,这些信息就是 TransactionSynchronizationManager 中记录的事务信息 。然后将这些信息保存在新的 DefaultTransactionStatus 对象中,便于内部事务运行结束后,恢复外层事务;
参考文章:
- Spring 事务实现分析
- Spring 中的 Advisor,Advice,Pointcut
- Spring事务失效的 8 大原因,这次可以吊打面试官了!
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
