天天看点

每日一点:带你了解spring中事务原理

作者:孙子代码
每日一点:带你了解spring中事务原理

在 Spring 框架中,事务是通过对应的 AOP 模块进行实现的。Spring AOP 模块为事务提供了面向切面编程的支持,它使用代理模式为方法调用添加了事务管理逻辑。

Spring 支持声明式事务管理和编程式事务管理两种方式,其中声明式事务管理通过配置元数据,而编程式事务管理则通过 API 进行管理。

在 Spring 中,声明式事务管理是基于切面的实现,通过使用 AspectJ AOP 框架来管理事务。事务切面通常是通过实现 TransactionAspectSupport 类来完成的。该类实现了 AspectJ 框架中的 Advice 接口,并且拥有 around 方法。通过 around 方法,TransactionAspectSupport 类能够在方法调用的前后执行事务管理的相关逻辑。

在声明式事务管理中,Spring 提供了 TransactionInterceptor 类来实现事务切面。TransactionInterceptor 实现了 MethodInterceptor 接口,并且它使用 TransactionAttributeSource 接口来确定事务属性。TransactionAttributeSource 接口定义了如何获取和解析事务元数据的方法。Spring 提供了多种 TransactionAttributeSource 的实现,如 AnnotationTransactionAttributeSource 和 NameMatchTransactionAttributeSource。

除了 TransactionInterceptor 类之外,Spring 还提供了 TransactionProxyFactoryBean 类。TransactionProxyFactoryBean 类是一个 FactoryBean,它用于为一个特定的目标对象生成一个事务代理对象。该代理对象使用事务拦截器包装目标对象,并将事务拦截器与目标对象绑定在一起。

具体来说,Spring通过将事务管理相关的代码织入到应用程序中,来实现事务管理的功能。这个过程包括以下几个步骤:

  1. 定义一个切面(Aspect),该切面表示事务管理的功能,比如在方法执行前启动事务,在方法执行后提交或回滚事务等等。
  2. 使用AOP代理技术将这个切面织入到应用程序中。具体来说,Spring使用代理工厂(ProxyFactory)来创建一个代理对象,该代理对象在运行时将切面织入到目标对象的方法调用中。
  3. 在应用程序中使用事务注解或编程式的方式来声明事务。在使用注解的情况下,Spring会扫描应用程序中带有事务注解的方法,然后为这些方法创建代理对象,并将事务管理的相关代码织入到代理对象中。在编程式的方式下,开发者需要手动获取事务管理器,并在代码中使用事务模板(TransactionTemplate)来管理事务。
  4. 根据事务的隔离级别、传播行为、超时时间等参数来控制事务的行为。在Spring中,事务管理器(TransactionManager)可以根据这些参数来创建和管理事务。

Spring中定义了七种事务传播行为,包括:

  1. REQUIRED(默认):如果当前存在事务,则加入该事务,否则新建一个事务。
  2. SUPPORTS:如果当前存在事务,则加入该事务,否则不使用事务。
  3. MANDATORY:必须在一个已有的事务中执行,否则抛出异常。
  4. REQUIRES_NEW:新建一个事务,并在该事务中执行。如果当前存在事务,则将当前事务挂起。
  5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将当前事务挂起。
  6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
  7. NESTED:如果当前存在事务,则在嵌套事务中执行。如果当前没有事务,则新建一个事务。

总的来说,Spring 的事务实现基于 AOP 技术,利用代理模式为方法调用添加了事务管理逻辑。Spring 提供了声明式事务管理和编程式事务管理两种方式。其中,声明式事务管理是基于切面实现的,通过 TransactionInterceptor 类来实现事务切面。同时,Spring 也提供了多种 TransactionAttributeSource 的实现,如 AnnotationTransactionAttributeSource 和 NameMatchTransactionAttributeSource。通过这些技术,Spring 实现了一个强大而灵活的事务管理框架,可以满足不同应用场景下的事务管理需求。

代码示例:

@Service
public class MyService {

    @Autowired
    private MyDao myDao;

    @Transactional(propagation = Propagation.REQUIRED)
    public void doSomething() {
        // ...
        myDao.update();
        doAnotherThing();
        // ...
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void doAnotherThing() {
        // ...
    }

}
           

在上述代码中,MyService类中定义了两个事务方法,doSomething()和doAnotherThing()。其中,doSomething()方法的事务传播行为为REQUIRED,doAnotherThing()方法的事务传播行为为REQUIRES_NEW。

假设当前线程中没有任何事务,调用doSomething()方法时,Spring将创建一个新的事务,并在该事务中执行myDao.update()方法。接着,Spring将调用doAnotherThing()方法,在该方法中创建了一个新的事务,并在该事务中执行相关操作。在doAnotherThing()方法执行完成后,Spring会将该事务提交或回滚,并将控制权交还给doSomething()方法。

最后,Spring将提交或回滚doSomething()方法的事务,并将控制权交还给调用方。如果在执行过程中发生了异常,Spring将回滚整个事务。

您会用了吗?