前言
Spring的spring-tx模块提供了对事务管理支持,使用Spring事务可以让我们从复杂的事务处理中得到解脱,无需去处理获得连接、关闭连接、事务提交和回滚等这些操作。Spring事务管理是Spring框架提供的一个核心功能,它允许开发者以声明式或编程式的方式管理事务,确保数据的一致性和完整性。
在Spring中,实现事务的方式有以下几种:
-
基于编程的事务管理:通过编程方式在业务方法中调用事务管理器的方法来手动控制事务的开启、提交、回滚或回滚指定异常。
-
基于注解的事务管理:通过在业务方法上使用@Transactional注解来指定事务的传播行为、隔离级别、超时时间、只读属性等。
-
基于XML配置的事务管理:通过在Spring的配置文件中配置事务代理工厂Bean,以及在目标对象的方法上使用事务通知器配置事务的属性。
-
基于AspectJ的事务管理:通过使用AspectJ来织入事务管理的切面,实现对业务方法的事务管理。
一、Spring事务的主要实现方式
Spring 提供了多种事务管理方式,主要包括编程式事务管理、声明式事务管理。
1)编程式事务管理:通过编程的方式管理事务,即通过编程方式在代码中显式地声明事务的开始、提交及回滚。
@Autowired
//transactionManager是某一个具体的PlatformTransactionManager实现类的对象
private PlatformTransactionManager transactionManager;public void someMethod() {//获取事务TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try {// 业务逻辑// ...//提交事务transactionManager.commit(status);} catch (RuntimeException e) {//回滚事务transactionManager.rollback(status);throw e;}
}
在使用编程式事务处理的过程中,利用 DefaultTransactionDefinition 对象来持有事务处理属性。同时,在创建事务的过程中得到一个 TransactionStatus 对象,然后通过直接调用transactionManager 对象 的 commit() 和 rollback()方法 来完成事务处理。
编程式事务管理允许开发者通过编程的方式直接控制事务的边界,包括事务的开始、提交和回滚。这种方式虽然提供了更高的灵活性,但会增加代码的复杂度,并且容易出错。
Spring提供了PlatformTransactionManager接口,用于编程式事务管理。开发者可以通过实现或注入该接口的实例,在代码中显式地控制事务。
2)声明式事务管理:通过 AOP 特性,对事务的管理通过注解或者配置文件的方式进行声明,从而使事务管理成为语言无关的行为。
@Transactional
public void someMethod() {// 业务逻辑// 方法执行完后,Spring会自动管理事务
}
在配置文件中开启声明式事务管理:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><context:annotation-config /><context:component-scan base-package="com.example.service" /><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><tx:annotation-driven transaction-manager="transactionManager" />
</beans>
注意:确保你的业务类被 Spring 管理,例如通过 @Component
或 @Service
注解。
声明式事务管理通过注解或XML配置的方式,将事务管理策略从业务代码中分离出来,让事务管理成为应用的一部分,而不是业务逻辑的一部分。这种方式使得事务管理与业务逻辑代码解耦,降低了代码的复杂度,提高了开发效率。
Spring通过@Transactional注解实现声明式事务管理。开发者只需在需要事务支持的方法或类上添加@Transactional注解,Spring容器就会自动为该方法或类创建代理对象,并在调用方法时应用事务管理逻辑。
在早期的Spring版本中,也支持通过XML配置文件来声明事务管理。这种方式相对繁琐,需要编写大量的XML配置,但随着注解的普及,这种方式已逐渐被淘汰。
二、Spring事务的实现原理
Spring事务管理的实现原理主要依赖于AOP(面向切面编程)和底层的事务管理器。
2.1、编程式事务
PlatformTransactionManager是Spring事务管理的核心接口,通过 PlatformTransactionManager 接口设计了一系列与事务处理息息相关的接口方法,如 getTransaction()、commit()、rollback() 这些和事务处理相关的统一接口。对于这些接口的实现,很大一部分是由 AbstractTransactionManager 抽象类来完成的。
AbstractPlatformManager 封装了 Spring 事务处理中通用的处理部分,比如事务的创建、提交、回滚,事务状态和信息的处理,与线程的绑定等,有了这些通用处理的支持,对于具体的事务管理器而言,它们只需要处理和具体数据源相关的组件设置就可以了,比如在DataSourceTransactionManager中,就只需要配置好和DataSource事务处理相关的接口以及相关的设置。
事务的创建:PlatformTransactionManager的getTransaction()方法,封装了底层事务的创建,并生成一个 TransactionStatus对象。AbstractPlatformTransactionManager提供了创建事务的模板,这个模板会被具体的事务处理器所使用。
事务创建的结果是生成一个TransactionStatus对象,通过这个对象来保存事务处理需要的基本信息,TransactionStatus的创建过程如下:
protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive();return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources);
}
以上是创建一个全新事务的过程,还有另一种情况是:在创建当前事务时,线程中已经有事务存在了。这种情况会涉及事务传播行为的处理。Spring中七种事务传播行为如下:
事务传播行为类型 | 描述 |
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
如果检测到已存在事务,handleExistingTransaction()方法将根据不同的事务传播行为类型执行相应逻辑。
PROPAGATION_NEVER
即当前方法需要在非事务的环境下执行,如果有事务存在,那么抛出异常。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");
}
PROPAGATION_NOT_SUPPORTED
与前者的区别在于,如果有事务存在,那么将事务挂起,而不是抛出异常。
事务的同步与传播行为
Spring事务还提供了事务的同步和传播行为等高级特性。事务的同步允许多个事务操作在同一线程中共享事务上下文,而事务的传播行为则定义了事务方法被另一个事务方法调用时的行为,如REQUIRED(如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务)REQUIRES_NEW(创建一个新的事务,并暂停当前事务(如果存在))等。
2.2、声明式事务
其底层建立在 AOP 的基础之上,对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。通过声明式事物,无需在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),便可以将事务规则应用到业务逻辑中。
TransactionInterceptor
TransactionInterceptor是spring事务提供的AOP拦截器,实现了AOP 的MethodInterceptor接口,是一种通知(advice)。其可以用于在方法调用前后进行事务管理。
@Nullablepublic Object invoke(MethodInvocation invocation) throws Throwable {Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {@Nullablepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}public Object getTarget() {return invocation.getThis();}public Object[] getArguments() {return invocation.getArguments();}});}
invokeWithinTransaction()方法会根据目标方法上的事务配置,来决定是开启新事务、加入已有事务,还是直接执行逻辑(如果没有事务)。
三、如何选择事务实现方式
当需要用到事务操作的地方很少的时候,那么就可以使用编程式事务方式 TransactionTemplate,它不会建立很多事务代理。但是,如果程序中用到大量的事务操作,声明式事务方式更适合,它使得事务管理和业务逻辑分离。
声明式事务管理只需要用到@Transactional 注解和@EnableTransactionManagement。它是基于 Spring AOP 实现的,并且通过注解实现,实现起来简单,对原有代码没有入侵性。
总结
Spring事务管理通过声明式事务和编程式事务两种方式,提供了灵活的事务管理策略。其中,声明式事务管理以其简洁性和高效性成为主流选择。编程式事务是指通过编码方式实现事务管理,缺点是与业务代码高度耦合,不同的业务代码需要编写不同的事务实现。声明式事务属于无侵入式,不会影响业务逻辑的实现。
Spring事务管理的实现原理主要依赖于AOP技术和事务管理器,通过动态代理机制将事务管理逻辑与业务逻辑解耦,实现了事务的透明化管理。理解Spring事务的实现方式和原理,对于开发高性能、高可靠性的企业级应用至关重要。