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完成注册
// 线程变量, scope为当前线程
private static final ThreadLocal LOCAL_HOOKS = new ThreadLocal();
public static void registerHook(TransactionHook transactionHook) {
if (transactionHook == null) {
throw new NullPointerException("transactionHook must not be null");
}
List transactionHooks = LOCAL_HOOKS.get();
if (transactionHooks == null) {
LOCAL_HOOKS.set(new ArrayList());
}
LOCAL_HOOKS.get().add(transactionHook);
}
2.2 获取
TransactionHookManager.java
public static List getHooks() throws IllegalStateException {
List hooks = LOCAL_HOOKS.get();
if (hooks == null || hooks.isEmpty()) {
return Collections.emptyList();
}
return Collections.unmodifiableList(hooks);
}
3. hook调用点
3.1 beforeBegin和beforeBegin
TransactionalTemplate.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
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
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块中执行。
public Object execute(TransactionalExecutor business) throws Throwable {
// 此处省略XXXX行
} finally {
//5. clear
resumeGlobalLockConfig(previousConfig);
triggerAfterCompletion();
cleanUp();
}
end.