likes
comments
collection
share

Spring的Transactional: 处理事务的强大工具

作者站长头像
站长
· 阅读数 18

引言:Spring的Transactional注解是框架中非常重要的一个特性,它为开发人员提供了方便的事务管理机制。Spring 事务管理分为编码式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式。

Spring的Transactional: 处理事务的强大工具

一.什么是事务?

  在软件开发中,事务是指由一系列操作组成的逻辑单元,这些操作要么全部成功地执行,要么全部回滚到初始状态,以保证数据的一致性和完整性。事务的使用非常重要,尤其是在处理数据库操作时。

  事务是数据库管理系统中的一条或者多条操作指令的集合,这些操作指令被封装为一个整体,以保证数据库的完整性、一致性和原子性。在事务中,所有操作都成功,事务才能提交,否则回滚,这样可以确保数据的一致性和完整性。

  事务具有以下四个特性:

  原子性(Atomicity):事务是一个原子操作单元,其对数据的修改要么全部执行,要么全不执行。

  一致性(Consistency):事务必须使数据库从一个状态改变为另一个状态。也就是说,事务开始之前和事务结束以后,数据库的完整性没有被破坏。

  隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务。

  持久性(Durability):一旦事务提交,则其结果永久保存在数据库中。即使系统崩溃,重新启动后数据库还能恢复到提交事务后的状态,保证事务的持久性。

  在关系型数据库中,对事务有如下要求:

  - 原子性:事务的原子性是指事务的操作要么全部完成,要么全部不完成。当一个事务中有一部分操作无法完成时,所有操作都需要回滚到操作前的状态。

  - 一致性:一致性是指在一个事务操作前后,数据库的数据应保持一致性状态,即满足数据库的约束、外键约束和参照完整性的要求。

  - 隔离性:隔离性是指在并发环境中,一个事务的执行不应影响其他事务的执行。

  - 持久性:持久性是指一旦一个事务提交,则其结果永久保存在数据库中。即使系统崩溃,重新启动后数据库还能恢复到提交事务后的状态。

二、Spring的Transactional注解

  在Spring框架中,Transactional注解是通过AOP(面向切面编程)来实现的。AOP允许我们在应用程序的关键部分插入代码,而不需要修改现有的业务逻辑。在事务管理中,我们可以使用Transactional注解将事务相关的行为织入到方法中。

  Spring的Transactional注解提供了以下三个关键功能:

   @Transactional:这个注解可以应用于类或方法上,表示该类或方法需要使用事务。当应用于类上时,该类中的所有public方法都将具有事务性。当应用于方法上时,只有该方法具有事务性。

  @Transactional(readOnly = true):这个注解表示该事务只读,不会对数据库进行写操作。这对于只读取数据而不修改数据的情况非常有用。

  @Transactional(rollbackFor = Exception.class):这个注解表示在指定异常的情况下回滚事务。例如,如果一个事务在执行过程中抛出了IOException,并且该事务的@Transactional注解中指定了rollbackFor = IOException.class,那么该事务将回滚并撤销之前的所有操作。

注解的定义

  首先,让我们来看一下Transactional注解的定义。Transactional注解在Spring框架中的实现类是org.springframework.transaction.annotation.Transactional。该注解可以应用在方法级别或类级别,用于标记需要进行事务管理的方法或类。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    // 事务的传播行为
    Propagation propagation() default Propagation.REQUIRED;

    // 事务的隔离级别
    Isolation isolation() default Isolation.DEFAULT;

    // 事务的超时时间
    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

    // 是否只读事务
    boolean readOnly() default false;

    // 触发事务回滚的异常
    Class<? extends Throwable>[] rollbackFor() default {};

    // 不触发事务回滚的异常
    Class<? extends Throwable>[] noRollbackFor() default {};
}

关注属性

  在Transactional注解中,有一些重要的属性需要我们关注:

  1. propagation:指定事务的传播行为。它定义了事务之间相互调用时事务的作用范围和行为。常用的传播行为包括REQUIRED、REQUIRES_NEW、SUPPORTS等。

  2. isolation:指定事务的隔离级别。它定义了多个事务同时对数据库进行读写操作时的处理方式。常用的隔离级别包括DEFAULT、READ_COMMITTED、READ_UNCOMMITTED等。

  3. timeout:指定事务的超时时间。如果事务在指定的时间内没有完成,将会被自动回滚。

  4. readOnly:指定事务是否只读。如果只进行读取操作,可以将readOnly属性设置为true,以提高性能。

  5. rollbackFor和noRollbackFor:用于指定触发事务回滚和不触发事务回滚的异常类。可以通过这两个属性来精确控制事务的回滚行为。

实现原理

  Transactional注解的实现原理是通过Spring AOP来实现的。Spring在运行时会通过AOP技术,对标记了@Transactional注解的方法进行代理,在代理对象中实现事务管理的相关逻辑。

  具体地说,Spring会在@Transactional注解的方法执行前开启一个事务,并在方法执行后根据执行的结果来决定是提交事务还是回滚事务。当方法调用其他的@Transactional方法时,如果这些方法在调用时没有创建新的事务,则会加入到已有的事务中。

  TransactionAspectSupport 是 Spring 框架中的一个类,它为事务切面的处理提供了支持。它提供了一些静态方法和实用函数,用于在代码中处理与事务相关的操作。

  主要的功能和方法包括:

  1. currentTransactionStatus():该方法用于获取当前事务的状态。它返回一个包含事务状态信息的 TransactionStatus 对象。

  2. currentTransactionInfo():该方法用于获取当前事务的详细信息。它返回一个包含事务信息的 TransactionInfo 对象,包括事务定义、事务管理器等。

  3. invokeWithinTransaction():该方法用于在方法调用内部执行带有事务的逻辑。它接受一个 TransactionCallback 对象作为参数,用于执行事务逻辑,并返回事务回调的结果。

  4. isTransactionActive():该方法用于检查当前是否存在活动的事务。如果有活动的事务存在,则返回 true;否则返回 false。

  在TransactionAspectSupport类中,有一个processAnnotationTransaction方法,它是@Transactional注解的核心处理方法。通过解析注解中的属性,创建TransactionAspectSupport类的实例,并调用实例的commitTransactionAfterReturningcompleteTransactionAfterThrowing方法来实现事务的提交或回滚,由于源码比较多,感兴趣的小伙伴可以自行阅读一下。

不生效场景

  Spring的Transactional注解在一些情况下可能不会生效,这些情况包括:

  1. 未被Spring容器管理的对象:Transactional注解只对被Spring容器管理的Bean生效。如果一个对象不是由Spring容器创建和管理的,那么Transactional注解将不起作用。确保被注解的类或方法是由Spring容器管理的Spring Bean。

  2. 缺少切面(Aspect):Transactional注解是通过AOP技术实现的,需要存在适当的切面来进行事务管理。如果应用程序中没有配置相应的切面或者AOP代理未生效,Transactional注解可能不会起作用。在配置文件中配置切面或使用@EnableTransactionManagement启用事务管理。

  3. 同类内部方法的调用:当在同一个类中的一个@Transactional方法从该类中的另一个方法调用时,事务不会应用。这是因为Spring使用基于代理的AOP机制来实现事务,对于类内部方法的调用,不会触发代理的逻辑,因此事务注解不会生效。

  4. 异常被捕获或处理:如果在@Transactional注解标记的方法中的异常被捕获或处理了,并且没有再次抛出异常,事务将不会回滚。默认情况下,只有未捕获的RuntimeException和Error才会触发事务回滚。如果遇到需要回滚事务的特定异常,可以使用rollbackFor属性来指定。

  5. 方法不是public修饰:Transactional注解只对public修饰的方法生效。对于非public修饰的方法,例如private或protected方法,Transactional注解将不起作用。

三、总结

  Spring的Transactional注解是一个强大且易用的工具,用于处理事务管理。它简化事务管理流程,提供声明式的事务管理方式,并具有灵活的事务控制能力。通过使用Transactional注解,开发人员可以更加专注于业务逻辑的实现,提升开发效率和代码的可维护性。因此,对于使用Spring框架的开发者来说,熟练掌握Transactional注解是非常重要的。

refs

转载自:https://juejin.cn/post/7275222603886641164
评论
请登录