Seata源码(八)Seata事务生命周期hook


Java极客 | 作者 / 铿然一叶 这是Java极客的第 99 篇原创文章


相关阅读:

萌新快速成长之路
JAVA编程思想(一)通过依赖注入增加扩展性
JAVA编程思想(二)如何面向接口编程
JAVA编程思想(三)去掉别扭的if,自注册策略模式优雅满足开闭原则
JAVA编程思想(四)Builder模式经典范式以及和工厂模式如何选?
Java编程思想(七)使用组合和继承的场景
JAVA基础(一)简单、透彻理解内部类和静态内部类
JAVA基础(二)内存优化-使用Java引用做缓存
JAVA基础(三)ClassLoader实现热加载
JAVA基础(四)枚举(enum)和常量定义,工厂类使用对比
JAVA基础(五)函数式接口-复用,解耦之利刃\
如何编写软件设计文档
Seata源码(一)初始化
Seata源码(二)事务基础对象
Seata源码(三)事务处理类结构和流程
Seata源码(四)全局锁GlobalLock
Seata源码(五)Seata数据库操作
Seata源码(六)Seata的undo日志操作
Seata源码(七)Seata事务故障处理\


1. hook概述

Seata提供给了事务处理hook,在事务的生命周期过程中可以扩展处理逻辑。事务hook,可由开发者定制实现,相关类结构如下:

描述
TransactionalTemplate 事务模版,在事务生命周期各个环节调用hook方法
TransactionHookManager 事务hook管理类,注册和获取hook
TransactionHook 事务生命周期hook接口
TransactionHookAdapter 事务生命周期hook默认实现,什么也没做,都是空方法

TransactionHook接口的方法都没有传入参数,只能通过线程变量获取相关数据,例如: RootContext.getXID()

此接口可能在实际使用中还有扩展空间,应允许传入一些需要的参数,否则能做的事情有限。

2. hook注册和获取

2.1 注册

直接调用TransactionHookManager的静态方法registerHook完成注册

java 复制代码
        // 线程变量, scope为当前线程
        private static final ThreadLocal<List<TransactionHook>> LOCAL_HOOKS = new ThreadLocal<>();

        public static void registerHook(TransactionHook transactionHook) {
            if (transactionHook == null) {
                throw new NullPointerException("transactionHook must not be null");
            }
            List<TransactionHook> transactionHooks = LOCAL_HOOKS.get();
            if (transactionHooks == null) {
                LOCAL_HOOKS.set(new ArrayList<>());
            }
            LOCAL_HOOKS.get().add(transactionHook);
        }

2.2 获取

TransactionHookManager.java

java 复制代码
    public static List<TransactionHook> getHooks() throws IllegalStateException {
        List<TransactionHook> hooks = LOCAL_HOOKS.get();

        if (hooks == null || hooks.isEmpty()) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableList(hooks);
    }

3. hook调用点

3.1 beforeBegin和beforeBegin

TransactionalTemplate.java

java 复制代码
    private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
        try {
            // TransactionHook.beforeBegin();
            triggerBeforeBegin();
            tx.begin(txInfo.getTimeOut(), txInfo.getName());
            // TransactionHook.afterBegin();
            triggerAfterBegin();
        } catch (TransactionException txe) {
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.BeginFailure);

        }
    }

    private void triggerBeforeBegin() {
        for (TransactionHook hook : getCurrentHooks()) {
            try {
                hook.beforeBegin();
            } catch (Exception e) {
                LOGGER.error("Failed execute beforeBegin in hook {}", e.getMessage(), e);
            }
        }
    }

    private void triggerAfterBegin() {
        for (TransactionHook hook : getCurrentHooks()) {
            try {
                hook.afterBegin();
            } catch (Exception e) {
                LOGGER.error("Failed execute afterBegin in hook {}", e.getMessage(), e);
            }
        }
    }

3.2 beforeCommit和afterCommit

TransactionalTemplate.java

java 复制代码
    private void commitTransaction(GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
        try {
            triggerBeforeCommit();
            tx.commit();
            triggerAfterCommit();
        } catch (TransactionException txe) {
            // 4.1 Failed to commit
            throw new TransactionalExecutor.ExecutionException(tx, txe,
                TransactionalExecutor.Code.CommitFailure);
        }
    }

triggerBeforeCommi和triggerAfterCommit方法调用逻辑同前。

3.3 beforeRollback和afterRollback

TransactionalTemplate.java

java 复制代码
    private void rollbackTransaction(GlobalTransaction tx, Throwable originalException) throws TransactionException, TransactionalExecutor.ExecutionException {
        triggerBeforeRollback();
        tx.rollback();
        triggerAfterRollback();
        // 3.1 Successfully rolled back
        throw new TransactionalExecutor.ExecutionException(tx, GlobalStatus.RollbackRetrying.equals(tx.getLocalStatus())
            ? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, originalException);
    }

triggerBeforeRollback和triggerAfterRollback方法调用逻辑同前。

3.4 afterCompletion

TransactionalTemplate.java 在所有操作执行完成后finally块中执行。

java 复制代码
    public Object execute(TransactionalExecutor business) throws Throwable {
            // 此处省略XXXX行
            } finally {
                //5. clear
                resumeGlobalLockConfig(previousConfig);
                triggerAfterCompletion();
                cleanUp();
            }

end.


<--阅过留痕,左边点赞!

相关推荐
nvd11几秒前
Java ETL - Apache Beam 简介
java·apache·etl
晴子呀17 分钟前
Spring底层原理大致脉络
java·后端·spring
只吹45°风23 分钟前
Java-ArrayList和LinkedList区别
java·arraylist·linkedlist·区别
阿华的代码王国31 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
黑蛋同志31 分钟前
array和linked list的区别
java
andrew_121937 分钟前
腾讯 IEG 游戏前沿技术 一面复盘
java·redis·sql·面试
寻求出路的程序媛1 小时前
JVM —— 类加载器的分类,双亲委派机制
java·jvm·面试
这孩子叫逆1 小时前
35. MyBatis中的缓存失效机制是如何工作的?
java·spring·mybatis
骆晨学长1 小时前
基于SpringBoot的校园失物招领系统
java·spring boot
汇匠源1 小时前
零工市场小程序:保障灵活就业
java·小程序·零工市场