• TransactionSynchronizationManager


    事务同步管理器

    1、TransactionSynchronizationManager

    操作多个方法 Spring 是如何来进行事务处理的呢?Spring 对于事务的管理都是基于 TransactionSynchronizationManager,下面我们就来简单的分析一下这个类。

    TransactionSynchronizationManager.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    private static final ThreadLocal<Map<Object, Object>> resources =
            new NamedThreadLocal<Map<Object, Object>>("Transactional resources");
     
    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
            new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");
     
    private static final ThreadLocal<String> currentTransactionName =
            new NamedThreadLocal<String>("Current transaction name");
     
    private static final ThreadLocal<Boolean> currentTransactionReadOnly =
            new NamedThreadLocal<Boolean>("Current transaction read-only status");
     
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
            new NamedThreadLocal<Integer>("Current transaction isolation level");
     
    private static final ThreadLocal<Boolean> actualTransactionActive =
            new NamedThreadLocal<Boolean>("Actual transaction active");

      

    这个对象里面通过 ThreadLocal 保存了线程需要状态以及资源对象。

    • resources:保存连接资源,因为一个方法里面可能包含两个事务(比如事务传播特性为:TransactionDefinition#PROPAGATION_REQUIRES_NEW),所以就用 Map 来保存资源.
    • synchronizations在进行数据库操作的时候,如果需要多个操作要么一起成功,要么一起失败那么就需要使用事务操作了。使用 Spring 框架只需要在方法上添加 @Transactional 注解这个方法就具有事务特性了。而且 Spring 也事务操作给开发者提供了很方便的扩展。:线程同步器,这个就是对 Spring 事务的扩展,通过 TransactionSynchronizationManager#registerSynchronization 来注册,我们稍后来分析这个对象在进行数据库操作的时候,如果需要多个操作要么一起成功,要么一起失败那么就需要使用事务操作了。使用 Spring 框架只需要在方法上添加 @Transactional 注解这个方法就具有事务特性了。而且 Spring 也事务操作给开发者提供了很方便的扩展。
    • currentTransactionReadOnly:用于保存当前事务是否只读
    • 在进行数据库操作的时候,如果需要多个操作要么一起成功,要么一起失败那么就需要使用事务操作了。使用 Spring 框架只需要在方法上添加 @Transactional 注解这个方法就具有事务特性了。而且 Spring 也事务操作给开发者提供了很方便的扩展。
    • currentTransactionName:用于保存当前事务名称,默认为空
    • currentTransactionIsolationLevel:用来保存当前事务的隔离级别
    • actualTransactionActive:用于保存当前事务是否还是 Active 状态

    下面我们来分析一下事务操作对于连接资源的处理,也就是事务处理中 TransactionSynchronizationManager 对于资源(resources 属性)的管理。关于 Spring 对于事务的处理可以看我之前的文章 – Spring Annotation Transaction

     

    2、Spring 事务的扩展 – TransactionSynchronization

    在上面的 TransactionSynchronizationManager 类中我们知道,事务操作的时候它的当前线程还保存了 TransactionSynchronization 对象。而这个对象伴随着 Spring 对 事务处理的各个生命周期都会有相应的扩展。

    TransactionSynchronization.java.

    public interface TransactionSynchronization extends Flushable {
    
        /** 事务提交状态 */
        int STATUS_COMMITTED = 0;
    
        /** 事务回滚状态 */
        int STATUS_ROLLED_BACK = 1;
    
        /**系统异常状态 */
        int STATUS_UNKNOWN = 2;
    
      //在spring开启新事务,获取connection之前会调用(未执行registCustomer) void suspend();
      //开启新事务失败时会调用(未执行registCustomer) void resume();
      //没调用 void flush(); // 事务提交之前 void beforeCommit(boolean readOnly); // 事务成功或者事务回滚之前 void beforeCompletion(); // 事务成功提交之后 void afterCommit(); // 操作完成之后(包含事务成功或者事务回滚) void afterCompletion(int status); }

    事务的事务扩展项目中的应用场景是当订单成功之后,发送一条消息到 MQ 当中去。由于事务是和数据库连接相绑定的,如果把发送消息和数据库操作放在一个事务里面。当发送消息时间过长时会占用数据库连接,所以就要把数据库操作与发送消息到 MQ 解耦开来。可以利用 TransactionSynchronization#afterCommit 的这个方法,当数据成功保存到数据库并且事务提交了就把消息发送到 MQ 里面。

    @Transactional
    public void finishOrder(Order order){
        // 修改订单成功
        updateOrderSuccess(order);
    
        // 发送消息到 MQ
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
           @Override
           public void afterCommit() {
               mqService.send(order);
           }
        });
    }

    当事务成功提交之后,就会把消息发送给 MQ,并且不会占用数据库连接资源。

    (1)、TransactionSynchronizationManager.registerSynchronization

    /**
     * Register a new transaction synchronization for the current thread.
     * Typically called by resource management code.
     * <p>Note that synchronizations can implement the
     * {@link org.springframework.core.Ordered} interface.
     * They will be executed in an order according to their order value (if any).
     * @param synchronization the synchronization object to register
     * @throws IllegalStateException if transaction synchronization is not active
     * @see org.springframework.core.Ordered
     */
    public static void registerSynchronization(TransactionSynchronization synchronization)
          throws IllegalStateException {
    
       Assert.notNull(synchronization, "TransactionSynchronization must not be null");
       if (!isSynchronizationActive()) {
          throw new IllegalStateException("Transaction synchronization is not active");
       }
       synchronizations.get().add(synchronization);
    }

    参考:https://zhuanlan.zhihu.com/p/375854755

      https://www.cnblogs.com/kkkfff/p/13778692.html




  • 相关阅读:
    How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04
    Mysql Docker Container Command
    svg_png
    png格式图片转为svg格式图片
    Ubuntu Server如何配置SFTP(建立用户监狱)
    ubuntu用户添加adduser, useradd并给予sudo权限
    Setup FTP server on Ubuntu 14.04
    Ubuntu Server 16.04.1系统安装
    1.Linux下生成密钥
    Linux查看设备命令
  • 原文地址:https://www.cnblogs.com/chenfx/p/15206606.html
Copyright © 2020-2023  润新知