所有文章
https://www.cnblogs.com/lay2017/p/12485081.html
正文
在上一篇文章中,我們看到被@GlobalTransactional或者@GlobalLock注解的方法,該Bean會做AOP事務增強。
本文將閱讀關於@GlobalTransactional的事務增強攔截器GlobalTransactionalInterceptor。首先,我們看一下它的UML類圖
GlobalTransactionalInterceptor設計路線只有兩條,一條是spring aop的方法攔截器,另一條是seata的配置變更監聽器。監聽器無非就是當配置變化的時候做回調處理,GlobalTransactionalInterceptor主要是監聽全局事務的關閉。
那么,我們關注點放在對MethodInterceptor的實現上,跟進invoke方法的實現
攔截器invoke方法
@Override public Object invoke(final MethodInvocation methodInvocation) throws Throwable { Class<?> targetClass = methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null; Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass); final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod); // 拿到@GlobalTransactional注解的元數據 final GlobalTransactional globalTransactionalAnnotation = getAnnotation(method, GlobalTransactional.class); // 拿到@GlobalLock注解的元數據 final GlobalLock globalLockAnnotation = getAnnotation(method, GlobalLock.class); // 處理@GlobalTransactional if (!disable && globalTransactionalAnnotation != null) { return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation); // 處理@GlobalLock } else if (!disable && globalLockAnnotation != null) { return handleGlobalLock(methodInvocation); // 直接調用原始方法 } else { return methodInvocation.proceed(); } }
如果事務是開啟的 disable=false,那么判斷方法是否有@GlobalTransactional或者@GlobalLock注解。如果有的話,那么執行對應的處理方法。如果沒有,那么直接執行proceed。
handleGlobalTransaction
handleGlobalTransaction處理@GlobalTransactional注解,跟進該方法
private Object handleGlobalTransaction(final MethodInvocation methodInvocation, final GlobalTransactional globalTrxAnno) throws Throwable { try { // 事務執行模板 return transactionalTemplate.execute(new TransactionalExecutor() { @Override public Object execute() throws Throwable { // 執行原始方法 return methodInvocation.proceed(); } public String name() { // 自定義或者格式化生成事務的名稱 String name = globalTrxAnno.name(); if (!StringUtils.isNullOrEmpty(name)) { return name; } return formatMethod(methodInvocation.getMethod()); } @Override public TransactionInfo getTransactionInfo() { // 將注解包裝成TransactionInfo對象 TransactionInfo transactionInfo = new TransactionInfo(); transactionInfo.setTimeOut(globalTrxAnno.timeoutMills()); transactionInfo.setName(name()); Set<RollbackRule> rollbackRules = new LinkedHashSet<>(); for (Class<?> rbRule : globalTrxAnno.rollbackFor()) { rollbackRules.add(new RollbackRule(rbRule)); } for (String rbRule : globalTrxAnno.rollbackForClassName()) { rollbackRules.add(new RollbackRule(rbRule)); } for (Class<?> rbRule : globalTrxAnno.noRollbackFor()) { rollbackRules.add(new NoRollbackRule(rbRule)); } for (String rbRule : globalTrxAnno.noRollbackForClassName()) { rollbackRules.add(new NoRollbackRule(rbRule)); } transactionInfo.setRollbackRules(rollbackRules); return transactionInfo; } }); } catch (TransactionalExecutor.ExecutionException e) { // 執行異常 TransactionalExecutor.Code code = e.getCode(); switch (code) { case RollbackDone: throw e.getOriginalException(); case BeginFailure: failureHandler.onBeginFailure(e.getTransaction(), e.getCause()); throw e.getCause(); case CommitFailure: failureHandler.onCommitFailure(e.getTransaction(), e.getCause()); throw e.getCause(); case RollbackFailure: failureHandler.onRollbackFailure(e.getTransaction(), e.getCause()); throw e.getCause(); default: throw new ShouldNeverHappenException("Unknown TransactionalExecutor.Code: " + code); } } }
可以看到攔截器把處理@GlobalTransactional的主體執行邏輯委托給了TransactionalTemplate這個模板的execute方法,而TransactionalExecutor執行器只是提供了執行原始方法,@GlobalTransactional元數據信息,事務名稱的實現。
handleGlobalLock
handleGlobalLock處理的是@GlobalLock的主體邏輯,比起TransactionalTemplate簡單了很多。
單純地把所有邏輯交給GlobalLockTemplate的execute方法,執行器只是負責執行原始方法
private Object handleGlobalLock(final MethodInvocation methodInvocation) throws Exception { return globalLockTemplate.execute(() -> { try { // 執行原始方法 return methodInvocation.proceed(); } catch (Throwable e) { if (e instanceof Exception) { throw (Exception)e; } else { throw new RuntimeException(e); } } }); }
總結
GlobalTransactionalInterceptor攔截器邏輯比較簡單,基本上都委托給了TransactionalTemplate和GlobalLockTemplate。攔截器只負責把對應的注解邏輯分發給對應的邏輯模板來處理。