You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@seata.apache.org by ji...@apache.org on 2024/03/08 14:34:57 UTC

(incubator-seata) branch 2.x updated: optimize: tcc compatible (#6387)

This is an automated email from the ASF dual-hosted git repository.

jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 4027ff8b88 optimize: tcc compatible (#6387)
4027ff8b88 is described below

commit 4027ff8b88de6e47322058b7f11682a5b3448e09
Author: wt_better <yi...@alibaba-inc.com>
AuthorDate: Fri Mar 8 22:34:53 2024 +0800

    optimize: tcc compatible (#6387)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 .../io/seata/core/model/TransactionManager.java    |  28 --
 .../seata/core/rpc/RegisterCheckAuthHandler.java   |  26 --
 .../api/interceptor/ActionInterceptorHandler.java  |  29 ++
 .../rm/tcc/api/BusinessActionContextParameter.java |  10 +-
 .../interceptor/TccActionInterceptorHandler.java   | 217 ++----------
 .../resource/parser/TccRegisterResourceParser.java |  56 ++--
 .../seata/spring/tcc/TccAnnotationProcessor.java   |  50 ---
 ...ation.tx.api.interceptor.parser.InterfaceParser |   3 +-
 ...x.api.interceptor.parser.RegisterResourceParser |   1 +
 ...eata.integration.tx.api.remoting.RemotingParser |   1 +
 .../java/io/seata/rm/tcc/BranchSessionMock.java    |  85 +++++
 .../test/java/io/seata/rm/tcc/NestTccAction.java   |  56 ++++
 .../java/io/seata/rm/tcc/NestTccActionImpl.java    |  59 ++++
 .../test/java/io/seata/rm/tcc/NormalTccAction.java |  72 ++++
 .../java/io/seata/rm/tcc/NormalTccActionImpl.java} |  38 ++-
 .../java/io/seata/rm/tcc/Param.java}               |  13 +-
 .../src/test/java/io/seata/rm/tcc/TccAction.java   |  67 ++++
 .../test/java/io/seata/rm/tcc/TccActionImpl.java   |  61 ++++
 .../java/io/seata/rm/tcc/TccParam.java}            |  46 ++-
 .../rm/tcc/interceptor/ProxyUtilsTccTest.java      |  34 +-
 .../parser/TccActionInterceptorParserTest.java     | 369 +++++++++++++++++++++
 .../BusinessActionContextParameterDesc.java        |  71 ----
 .../rm/tcc/api/BusinessActionContextParameter.java |  12 +-
 .../seata/spring/tcc/TccAnnotationProcessor.java   |   3 +-
 .../interceptor/TccActionInterceptorHandler.java   |  77 +++--
 .../resource/parser/TccRegisterResourceParser.java |  11 +-
 .../rm/tcc/interceptor/ProxyUtilsTccTest.java      |  12 +-
 29 files changed, 1035 insertions(+), 474 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index c0680127c4..1f8275e60e 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -107,6 +107,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#6386](https://github.com/apache/incubator-seata/pull/6386)] replace `byte-buddy` to JDK proxy in `ConfigurationCache`
 - [[#6391](https://github.com/apache/incubator-seata/pull/6091)] forbid duplicate registration of TCC resources
 - [[#6393](https://github.com/apache/incubator-seata/pull/6393)] determine the version before sync metadata and add retry mechanism
+- [[#6387](https://github.com/apache/incubator-seata/pull/6387)] optimize tcc use compatible
 
 ### refactor:
 - [[#6269](https://github.com/apache/incubator-seata/pull/6269)] standardize Seata Exception
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 5d3eaf99eb..bdf42b02e5 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -111,6 +111,7 @@
 - [[#6386](https://github.com/apache/incubator-seata/pull/6386)] 在 `ConfigurationCache` 类中,将 `byte-buddy` 替换为JDK代理
 - [[#6391](https://github.com/apache/incubator-seata/pull/6091)] 禁止重复注册TCC资源
 - [[#6393](https://github.com/apache/incubator-seata/pull/6393)] 元数据同步前判断版本,并增加重试功能
+- [[#6387](https://github.com/apache/incubator-seata/pull/6387)] 优化tcc使用兼容
 
 
 ### refactor:
diff --git a/compatible/src/main/java/io/seata/core/model/TransactionManager.java b/compatible/src/main/java/io/seata/core/model/TransactionManager.java
deleted file mode 100644
index 5f03357db5..0000000000
--- a/compatible/src/main/java/io/seata/core/model/TransactionManager.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.core.model;
-
-/**
- * 
- *
- * Transaction Manager.
- *
- * Define a global transaction and control it.
- *
- */
-public interface TransactionManager extends org.apache.seata.core.model.TransactionManager {
-}
diff --git a/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java b/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java
deleted file mode 100644
index 42b137a475..0000000000
--- a/compatible/src/main/java/io/seata/core/rpc/RegisterCheckAuthHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.core.rpc;
-
-/**
- * 
- *
- * The interface Register check auth handler.
- *
- */
-public interface RegisterCheckAuthHandler extends org.apache.seata.core.rpc.RegisterCheckAuthHandler {
-}
diff --git a/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java b/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
index a21b897a49..2a765ad943 100644
--- a/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
+++ b/compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
@@ -16,6 +16,7 @@
  */
 package io.seata.integration.tx.api.interceptor;
 
+import io.seata.rm.tcc.api.BusinessActionContext;
 import io.seata.rm.tcc.api.BusinessActionContextParameter;
 import org.apache.seata.rm.tcc.api.ParamType;
 
@@ -30,6 +31,34 @@ import java.util.Map;
 @Deprecated
 public class ActionInterceptorHandler extends org.apache.seata.integration.tx.api.interceptor.ActionInterceptorHandler {
 
+    protected BusinessActionContext getOrCreateActionContextAndResetToArguments(Class<?>[] parameterTypes, Object[] arguments) {
+        BusinessActionContext actionContext = null;
+
+        // get the action context from arguments
+        int argIndex = 0;
+        for (Class<?> parameterType : parameterTypes) {
+            if (BusinessActionContext.class.isAssignableFrom(parameterType)) {
+                actionContext = (BusinessActionContext) arguments[argIndex];
+                if (actionContext == null) {
+                    // If the action context exists in arguments but is null, create a new one and reset the action context to the arguments
+                    actionContext = new BusinessActionContext();
+                    arguments[argIndex] = actionContext;
+                } else {
+                    // Reset the updated, avoid unnecessary reporting
+                    actionContext.setUpdated(null);
+                }
+                break;
+            }
+            argIndex++;
+        }
+
+        // if null, create a new one
+        if (actionContext == null) {
+            actionContext = new BusinessActionContext();
+        }
+        return actionContext;
+    }
+
 
     /**
      * Extracting context data from parameters, add them to the context
diff --git a/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java b/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
index d9649587ef..ad4ef05c2f 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/api/BusinessActionContextParameter.java
@@ -29,7 +29,7 @@ public @interface BusinessActionContextParameter {
      * parameter's name. Synonym for {@link #paramName()}.
      *
      * @return the name of the param or field
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+     * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
      */
     String value() default "";
 
@@ -37,7 +37,7 @@ public @interface BusinessActionContextParameter {
      * parameter's name. Synonym for {@link #value()}.
      *
      * @return the name of the param or field
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+     * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
      */
     String paramName() default "";
 
@@ -54,7 +54,7 @@ public @interface BusinessActionContextParameter {
      * Specify the index of the parameter in the List
      *
      * @return the index of the List
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getByIndex
+     * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#getByIndex
      */
     int index() default -1;
 
@@ -63,8 +63,8 @@ public @interface BusinessActionContextParameter {
      * if {@code index >= 0}, the object get from the List and then do get the parameter from the property of the object
      *
      * @return the boolean
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject
+     * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
+     * @see io.seata.integration.tx.api.interceptor.ActionContextUtil#fetchContextFromObject
      */
     boolean isParamInProperty() default false;
 }
diff --git a/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java b/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
index 25d19a588a..5b570e5b63 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
@@ -16,209 +16,52 @@
  */
 package io.seata.rm.tcc.interceptor;
 
-import io.seata.core.context.RootContext;
-import io.seata.core.model.BranchType;
-import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
-import org.apache.seata.common.Constants;
-import org.apache.seata.common.holder.ObjectHolder;
-import org.apache.seata.common.util.ReflectionUtil;
-import org.apache.seata.integration.tx.api.fence.config.CommonFenceConfig;
-import org.apache.seata.integration.tx.api.interceptor.InvocationWrapper;
-import org.apache.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
-import org.slf4j.MDC;
-
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
-import static org.apache.seata.common.Constants.BEAN_NAME_SPRING_FENCE_CONFIG;
+import io.seata.integration.tx.api.interceptor.ActionInterceptorHandler;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+import org.apache.seata.common.Constants;
+import org.apache.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
 
 public class TccActionInterceptorHandler extends org.apache.seata.rm.tcc.interceptor.TccActionInterceptorHandler {
 
     public TccActionInterceptorHandler(Object targetBean, Set<String> methodsToProxy) {
         super(targetBean, methodsToProxy);
+        actionInterceptorHandler = new ActionInterceptorHandler();
     }
 
     @Override
-    protected Object doInvoke(InvocationWrapper invocation) throws Throwable {
-        if (!RootContext.inGlobalTransaction() || RootContext.inSagaBranch()) {
-            //not in transaction, or this interceptor is disabled
-            return invocation.proceed();
-        }
-        Method method = invocation.getMethod();
-        TwoPhaseBusinessAction businessAction = parseAnnotation(method);
-
-        //try method
-        if (businessAction != null) {
-            //save the xid
-            String xid = RootContext.getXID();
-            //save the previous branchType
-            BranchType previousBranchType = RootContext.getBranchType();
-            //if not TCC, bind TCC branchType
-            if (BranchType.TCC != previousBranchType) {
-                RootContext.bindBranchType(BranchType.TCC);
-            }
-            try {
-                TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
-                businessActionParam.setActionName(businessAction.name());
-                businessActionParam.setDelayReport(businessAction.isDelayReport());
-                businessActionParam.setUseCommonFence(businessAction.useTCCFence());
-                businessActionParam.setBranchType(org.apache.seata.core.model.BranchType.TCC);
-                Map<String, Object> businessActionContextMap = new HashMap<>(4);
-                //the phase two method name
-                businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
-                businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
-                businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
-                businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
-                businessActionParam.setBusinessActionContext(businessActionContextMap);
-                //Handler the TCC Aspect, and return the business result
-                return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam,
-                        invocation::proceed);
-            } finally {
-                //if not TCC, unbind branchType
-                if (BranchType.TCC != previousBranchType) {
-                    RootContext.unbindBranchType();
-                }
-                //MDC remove branchId
-                MDC.remove(org.apache.seata.core.context.RootContext.MDC_KEY_BRANCH_ID);
-            }
-        }
-
-        //not TCC try method
-        return invocation.proceed();
-    }
-
-    private TwoPhaseBusinessAction parseAnnotation(Method methodKey) throws NoSuchMethodException {
-        TwoPhaseBusinessAction result = convertIoSeata(parseAnnotationCache.computeIfAbsent(methodKey, method -> {
-            TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
-            if (businessAction == null && targetBean.getClass() != null) {
-                Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass());
-                if (interfaceClasses != null) {
-                    for (Class<?> interClass : interfaceClasses) {
-                        try {
-                            Method m = interClass.getMethod(method.getName(), method.getParameterTypes());
-                            businessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
-                            if (businessAction != null) {
-                                // init common fence clean task if enable useTccFence
-                                initCommonFenceCleanTask(businessAction);
-                                break;
-                            }
-                        } catch (NoSuchMethodException e) {
-                            throw new RuntimeException(e);
-                        }
-                    }
-                }
-            }
-            return convertApacheSeata(businessAction);
-        }));
-        return result;
+    protected Class<? extends Annotation> getAnnotationClass() {
+        return TwoPhaseBusinessAction.class;
     }
 
-    private org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction convertApacheSeata(TwoPhaseBusinessAction twoPhaseBusinessAction) {
-        org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction result = new org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction() {
-
-            @Override
-            public Class<? extends Annotation> annotationType() {
-                return org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction.class;
-            }
-
-            @Override
-            public String name() {
-                return twoPhaseBusinessAction.name();
-            }
-
-            @Override
-            public String commitMethod() {
-                return twoPhaseBusinessAction.commitMethod();
-            }
-
-            @Override
-            public String rollbackMethod() {
-                return twoPhaseBusinessAction.rollbackMethod();
-            }
-
-            @Override
-            public boolean isDelayReport() {
-                return twoPhaseBusinessAction.isDelayReport();
-            }
-
-            @Override
-            public boolean useTCCFence() {
-                return twoPhaseBusinessAction.useTCCFence();
-            }
-
-            @Override
-            public Class<?>[] commitArgsClasses() {
-                return twoPhaseBusinessAction.commitArgsClasses();
-            }
-
-            @Override
-            public Class<?>[] rollbackArgsClasses() {
-                return twoPhaseBusinessAction.rollbackArgsClasses();
-            }
-        };
-        return result;
-    }
-
-    private TwoPhaseBusinessAction convertIoSeata(org.apache.seata.rm.tcc.api.TwoPhaseBusinessAction twoPhaseBusinessAction) {
-        TwoPhaseBusinessAction result = new TwoPhaseBusinessAction() {
-            @Override
-            public Class<? extends Annotation> annotationType() {
-                return TwoPhaseBusinessAction.class;
-            }
-
-            @Override
-            public String name() {
-                return twoPhaseBusinessAction.name();
-            }
-
-            @Override
-            public String commitMethod() {
-                return twoPhaseBusinessAction.commitMethod();
-            }
-
-            @Override
-            public String rollbackMethod() {
-                return twoPhaseBusinessAction.rollbackMethod();
-            }
-
-            @Override
-            public boolean isDelayReport() {
-                return twoPhaseBusinessAction.isDelayReport();
-            }
-
-            @Override
-            public boolean useTCCFence() {
-                return twoPhaseBusinessAction.useTCCFence();
-            }
-
-            @Override
-            public Class<?>[] commitArgsClasses() {
-                return twoPhaseBusinessAction.commitArgsClasses();
-            }
-
-            @Override
-            public Class<?>[] rollbackArgsClasses() {
-                return twoPhaseBusinessAction.rollbackArgsClasses();
-            }
-        };
-        return result;
-    }
-
-
-    private void initCommonFenceCleanTask(TwoPhaseBusinessAction twoPhaseBusinessAction) {
-        CommonFenceConfig commonFenceConfig = (CommonFenceConfig) ObjectHolder.INSTANCE.getObject(BEAN_NAME_SPRING_FENCE_CONFIG);
-        if (commonFenceConfig == null || commonFenceConfig.getInitialized().get()) {
-            return;
-        }
-        if (twoPhaseBusinessAction != null && twoPhaseBusinessAction.useTCCFence()) {
-            if (commonFenceConfig.getInitialized().compareAndSet(false, true)) {
-                // init common fence clean task if enable useTccFence
-                commonFenceConfig.init();
-            }
+    @Override
+    protected boolean parserCommonFenceConfig(Annotation annotation) {
+        if (annotation == null) {
+            return false;
         }
+        TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+        return businessAction.useTCCFence();
     }
 
+    @Override
+    protected TwoPhaseBusinessActionParam createTwoPhaseBusinessActionParam(Annotation annotation) {
+        TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+        TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
+        businessActionParam.setActionName(businessAction.name());
+        businessActionParam.setDelayReport(businessAction.isDelayReport());
+        businessActionParam.setUseCommonFence(businessAction.useTCCFence());
+        businessActionParam.setBranchType(getBranchType());
+        Map<String, Object> businessActionContextMap = new HashMap<>(4);
+        //the phase two method name
+        businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
+        businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
+        businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
+        businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
+        businessActionParam.setBusinessActionContext(businessActionContextMap);
+        return businessActionParam;
+    }
 }
diff --git a/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java b/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
index b1570ec419..465d4337ac 100644
--- a/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
+++ b/compatible/src/main/java/io/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
@@ -16,36 +16,22 @@
  */
 package io.seata.rm.tcc.resource.parser;
 
+import io.seata.integration.tx.api.interceptor.ActionContextUtil;
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
 import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
 import org.apache.seata.common.exception.FrameworkException;
-import org.apache.seata.common.util.ReflectionUtil;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.rm.DefaultResourceManager;
 import org.apache.seata.rm.tcc.TCCResource;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashSet;
 import java.util.Set;
 
 public class TccRegisterResourceParser extends org.apache.seata.rm.tcc.resource.parser.TccRegisterResourceParser {
 
-    @Override
-    public void registerResource(Object target, String beanName) {
-        try {
-            //service bean, registry resource
-            Class<?> serviceClass = target.getClass();
-            this.executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
-            Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
-            for (Class<?> interClass : interfaceClasses) {
-                this.executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
-            }
-        } catch (Throwable t) {
-            throw new FrameworkException(t, "parser remoting service error");
-        }
-    }
-
-    private void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
+    protected void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
         for (Method m : methods) {
             TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
             if (twoPhaseBusinessAction != null) {
@@ -66,13 +52,41 @@ public class TccRegisterResourceParser extends org.apache.seata.rm.tcc.resource.
                 tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
                 tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
                 // set phase two method's keys
-                tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
+                tccResource.setPhaseTwoCommitKeys(getTwoPhaseArgs(tccResource.getCommitMethod(),
                         twoPhaseBusinessAction.commitArgsClasses()));
-                tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
+                tccResource.setPhaseTwoRollbackKeys(getTwoPhaseArgs(tccResource.getRollbackMethod(),
                         twoPhaseBusinessAction.rollbackArgsClasses()));
                 //registry tcc resource
                 DefaultResourceManager.get().registerResource(tccResource);
             }
         }
     }
+
+    @Override
+    protected String[] getTwoPhaseArgs(Method method, Class<?>[] argsClasses) {
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        String[] keys = new String[parameterAnnotations.length];
+        /*
+         * get parameter's key
+         * if method's parameter list is like
+         * (BusinessActionContext, @BusinessActionContextParameter("a") A a, @BusinessActionContextParameter("b") B b)
+         * the keys will be [null, a, b]
+         */
+        for (int i = 0; i < parameterAnnotations.length; i++) {
+            for (int j = 0; j < parameterAnnotations[i].length; j++) {
+                if (parameterAnnotations[i][j] instanceof BusinessActionContextParameter) {
+                    BusinessActionContextParameter param = (BusinessActionContextParameter) parameterAnnotations[i][j];
+                    String key = ActionContextUtil.getParamNameFromAnnotation(param);
+                    keys[i] = key;
+                    break;
+                }
+            }
+            if (keys[i] == null && !(argsClasses[i].equals(BusinessActionContext.class))) {
+                throw new IllegalArgumentException("non-BusinessActionContext parameter should use annotation " +
+                    "BusinessActionContextParameter");
+            }
+        }
+        return keys;
+    }
+
 }
diff --git a/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java b/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java
deleted file mode 100644
index 9e7744928a..0000000000
--- a/compatible/src/main/java/io/seata/spring/tcc/TccAnnotationProcessor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package io.seata.spring.tcc;
-
-import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
-import org.apache.seata.integration.tx.api.remoting.RemotingDesc;
-import org.apache.seata.integration.tx.api.util.ProxyUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-public class TccAnnotationProcessor extends org.apache.seata.spring.tcc.TccAnnotationProcessor {
-    private static final Logger LOGGER = LoggerFactory.getLogger(org.apache.seata.spring.tcc.TccAnnotationProcessor.class);
-
-    @Override
-    public void addTccAdvise(Object bean, String beanName, Field field, Class serviceClass) throws IllegalAccessException {
-        Object fieldValue = field.get(bean);
-        if (fieldValue == null) {
-            return;
-        }
-        for (Method method : field.getType().getMethods()) {
-            if (!Modifier.isStatic(method.getModifiers()) && (method.isAnnotationPresent(TwoPhaseBusinessAction.class))) {
-                RemotingDesc remotingDesc = new RemotingDesc();
-                remotingDesc.setServiceClass(serviceClass);
-
-                Object proxyBean = ProxyUtil.createProxy(bean, beanName);
-                field.setAccessible(true);
-                field.set(bean, proxyBean);
-                LOGGER.info("Bean[" + bean.getClass().getName() + "] with name [" + field.getName() + "] would use proxy");
-            }
-        }
-    }
-}
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
index b9e1043dc3..3bf5b41bb2 100644
--- a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.InterfaceParser
@@ -1 +1,2 @@
-io.seata.integration.tx.api.interceptor.parser.GlobalTransactionalInterceptorParser
\ No newline at end of file
+io.seata.rm.tcc.interceptor.parser.TccActionInterceptorParser
+io.seata.integration.tx.api.interceptor.parser.GlobalTransactionalInterceptorParser
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser
new file mode 100644
index 0000000000..9501e9d87c
--- /dev/null
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.interceptor.parser.RegisterResourceParser
@@ -0,0 +1 @@
+io.seata.rm.tcc.resource.parser.TccRegisterResourceParser
\ No newline at end of file
diff --git a/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser
new file mode 100644
index 0000000000..78ff6f2e84
--- /dev/null
+++ b/compatible/src/main/resources/META-INF/services/org.apache.seata.integration.tx.api.remoting.RemotingParser
@@ -0,0 +1 @@
+io.seata.rm.tcc.remoting.parser.LocalTCCRemotingParser
\ No newline at end of file
diff --git a/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java b/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java
new file mode 100644
index 0000000000..9ec015d11e
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/BranchSessionMock.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+
+import org.apache.seata.core.model.BranchType;
+
+public class BranchSessionMock {
+
+    private String xid;
+
+    private long branchId;
+
+    private String resourceGroupId;
+
+    private String resourceId;
+
+
+    private BranchType branchType;
+
+
+    private String applicationData;
+
+
+    public String getXid() {
+        return xid;
+    }
+
+    public void setXid(String xid) {
+        this.xid = xid;
+    }
+
+    public long getBranchId() {
+        return branchId;
+    }
+
+    public void setBranchId(long branchId) {
+        this.branchId = branchId;
+    }
+
+    public String getResourceGroupId() {
+        return resourceGroupId;
+    }
+
+    public void setResourceGroupId(String resourceGroupId) {
+        this.resourceGroupId = resourceGroupId;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public BranchType getBranchType() {
+        return branchType;
+    }
+
+    public void setBranchType(BranchType branchType) {
+        this.branchType = branchType;
+    }
+
+    public String getApplicationData() {
+        return applicationData;
+    }
+
+    public void setApplicationData(String applicationData) {
+        this.applicationData = applicationData;
+    }
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java b/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java
new file mode 100644
index 0000000000..fe74cc0bd0
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NestTccAction.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ */
+@LocalTCC
+public interface NestTccAction {
+
+    /**
+     * Prepare boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    @TwoPhaseBusinessAction(name = "tccNestActionForCompatibleTest")
+    boolean prepare(BusinessActionContext actionContext, int count);
+
+    @TwoPhaseBusinessAction(name = "tccNestActionRequiredNewForCompatibleTest")
+    boolean prepareNestRequiredNew(BusinessActionContext actionContext, int count);
+
+    /**
+     * Commit boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean commit(BusinessActionContext actionContext);
+
+    /**
+     * Rollback boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean rollback(BusinessActionContext actionContext);
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java b/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java
new file mode 100644
index 0000000000..0b34b57e9e
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NestTccActionImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.spring.annotation.GlobalTransactional;
+import io.seata.tm.api.transaction.Propagation;
+
+public class NestTccActionImpl implements NestTccAction {
+
+    private TccAction tccAction;
+    private boolean isCommit;
+
+    @Override
+    @GlobalTransactional()
+    public boolean prepare(BusinessActionContext actionContext, int count) {
+        tccAction.prepare(actionContext);
+        return count > 1;
+    }
+
+    @GlobalTransactional(propagation = Propagation.REQUIRES_NEW)
+    @Override
+    public boolean prepareNestRequiredNew(BusinessActionContext actionContext, int count) {
+        tccAction.prepare(actionContext);
+        return count > 1;
+    }
+
+    @Override
+    public boolean commit(BusinessActionContext actionContext) {
+        isCommit = true;
+        return true;
+    }
+
+    @Override
+    public boolean rollback(BusinessActionContext actionContext) {
+        return true;
+    }
+
+    public void setTccAction(TccAction tccAction) {
+        this.tccAction = tccAction;
+    }
+
+    public boolean isCommit() {
+        return isCommit;
+    }
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java b/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java
new file mode 100644
index 0000000000..58221f4bae
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/NormalTccAction.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+
+import java.util.List;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ *
+ */
+@LocalTCC
+public interface NormalTccAction {
+
+    /**
+     * Prepare boolean.
+     *
+     * @param actionContext the action context
+     * @param a             the a
+     * @param b             the b
+     * @param tccParam      the tcc param
+     * @return the boolean
+     */
+    @TwoPhaseBusinessAction(name = "tccActionForCompatibleTest", commitMethod = "commit", rollbackMethod = "rollback", commitArgsClasses = {BusinessActionContext.class, TccParam.class}, rollbackArgsClasses = {BusinessActionContext.class, TccParam.class})
+    String prepare(BusinessActionContext actionContext,
+                    @BusinessActionContextParameter("a") int a,
+                    @BusinessActionContextParameter(paramName = "b", index = 0) List b,
+                    @BusinessActionContextParameter(isParamInProperty = true) TccParam tccParam);
+
+    /**
+     * Commit boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean commit(BusinessActionContext actionContext,
+                   @BusinessActionContextParameter("tccParam") TccParam param);
+
+    /**
+     * Rollback boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean rollback(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam") TccParam param);
+
+
+    @TwoPhaseBusinessAction(name = "tccActionForCompatibleTestWithException", commitMethod = "commit", rollbackMethod = "rollback", commitArgsClasses = {BusinessActionContext.class, TccParam.class}, rollbackArgsClasses = {BusinessActionContext.class, TccParam.class})
+    String prepareWithException(BusinessActionContext actionContext,
+                   @BusinessActionContextParameter("a") int a,
+                   @BusinessActionContextParameter(paramName = "b", index = 0) List b,
+                   @BusinessActionContextParameter(isParamInProperty = true) TccParam tccParam);
+
+}
diff --git a/compatible/src/main/java/io/seata/metrics/exporter/Exporter.java b/compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
similarity index 50%
rename from compatible/src/main/java/io/seata/metrics/exporter/Exporter.java
rename to compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
index 612b848442..b3dcc1a17b 100644
--- a/compatible/src/main/java/io/seata/metrics/exporter/Exporter.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/NormalTccActionImpl.java
@@ -14,12 +14,38 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.seata.metrics.exporter;
+package io.seata.rm.tcc;
 
 
-/**
- * Exporter interface for metrics
- *
- */
-public interface Exporter extends org.apache.seata.metrics.exporter.Exporter {
+import java.util.List;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+
+
+public class NormalTccActionImpl implements NormalTccAction {
+
+    @Override
+    public String prepare(BusinessActionContext actionContext, int a, List b, TccParam tccParam) {
+        return "a";
+    }
+
+    @Override
+    public boolean commit(BusinessActionContext actionContext, TccParam param) {
+        return false;
+    }
+
+    @Override
+    public boolean rollback(BusinessActionContext actionContext, TccParam param) {
+        return false;
+    }
+
+    public boolean otherMethod() {
+        return true;
+    }
+
+    @Override
+    public String prepareWithException(BusinessActionContext actionContext, int a, List b, TccParam tccParam) {
+        throw new IllegalArgumentException();
+    }
+
 }
diff --git a/compatible/src/main/java/io/seata/metrics/registry/Registry.java b/compatible/src/test/java/io/seata/rm/tcc/Param.java
similarity index 69%
rename from compatible/src/main/java/io/seata/metrics/registry/Registry.java
rename to compatible/src/test/java/io/seata/rm/tcc/Param.java
index 7bb8b78f79..65af4f832a 100644
--- a/compatible/src/main/java/io/seata/metrics/registry/Registry.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/Param.java
@@ -14,12 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.seata.metrics.registry;
+package io.seata.rm.tcc;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
- * Registry interface for metrics
+ * customized annotation
  *
  */
-public interface Registry extends org.apache.seata.metrics.registry.Registry {
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+public @interface Param {
+    String value() default "";
 }
diff --git a/compatible/src/test/java/io/seata/rm/tcc/TccAction.java b/compatible/src/test/java/io/seata/rm/tcc/TccAction.java
new file mode 100644
index 0000000000..2f2037ebe0
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccAction.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
+import io.seata.rm.tcc.api.LocalTCC;
+import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
+
+/**
+ * The interface Tcc action.
+ */
+@LocalTCC
+public interface TccAction {
+
+    /**
+     * Prepare boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    @TwoPhaseBusinessAction(name = "tccActionForTest")
+    boolean prepare(BusinessActionContext actionContext);
+
+    /**
+     * Commit boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean commit(BusinessActionContext actionContext);
+
+    /**
+     * Commit boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean commitWithArg(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam")
+    TccParam param, @Param("a") Integer a);
+
+    /**
+     * Rollback boolean.
+     *
+     * @param actionContext the action context
+     * @return the boolean
+     */
+    boolean rollback(BusinessActionContext actionContext);
+
+    boolean rollbackWithArg(BusinessActionContext actionContext, @BusinessActionContextParameter("tccParam")
+    TccParam param);
+
+}
diff --git a/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java b/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java
new file mode 100644
index 0000000000..f3d5dba0f4
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccActionImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc;
+
+import io.seata.rm.tcc.api.BusinessActionContext;
+
+/**
+ * The type Tcc action.
+ *
+ */
+public class TccActionImpl implements TccAction {
+
+    private boolean isCommit;
+
+
+    @Override
+    public boolean prepare(BusinessActionContext actionContext) {
+        return true;
+    }
+
+    @Override
+    public boolean commit(BusinessActionContext actionContext) {
+        isCommit = true;
+        return true;
+    }
+
+    @Override
+    public boolean commitWithArg(BusinessActionContext actionContext, TccParam param, Integer a) {
+        return false;
+    }
+
+
+    @Override
+    public boolean rollback(BusinessActionContext actionContext) {
+        return true;
+    }
+
+    @Override
+    public boolean rollbackWithArg(BusinessActionContext actionContext, TccParam param) {
+        return false;
+    }
+
+
+    public boolean isCommit() {
+        return isCommit;
+    }
+}
diff --git a/compatible/src/main/java/io/seata/core/model/ResourceManager.java b/compatible/src/test/java/io/seata/rm/tcc/TccParam.java
similarity index 51%
rename from compatible/src/main/java/io/seata/core/model/ResourceManager.java
rename to compatible/src/test/java/io/seata/rm/tcc/TccParam.java
index 01420df6a5..da82abaeee 100644
--- a/compatible/src/main/java/io/seata/core/model/ResourceManager.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/TccParam.java
@@ -14,13 +14,53 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.seata.core.model;
+package io.seata.rm.tcc;
 
+import io.seata.rm.tcc.api.BusinessActionContextParameter;
 
 /**
- * Resource Manager: common behaviors.
+ * The type Tcc param.
  *
  */
-public interface ResourceManager extends org.apache.seata.core.model.ResourceManager {
+public class TccParam {
 
+    /**
+     * The Num.
+     */
+    protected int num;
+
+    /**
+     * The Email.
+     */
+    @BusinessActionContextParameter(paramName = "email")
+    protected String email;
+
+    /**
+     * Instantiates a new Tcc param.
+     *
+     * @param num   the num
+     * @param email the email
+     */
+    public TccParam(int num, String email) {
+        this.num = num;
+        this.email = email;
+    }
+
+    /**
+     * Gets num.
+     *
+     * @return the num
+     */
+    public int getNum() {
+        return num;
+    }
+
+    /**
+     * Sets num.
+     *
+     * @param num the num
+     */
+    public void setNum(int num) {
+        this.num = num;
+    }
 }
diff --git a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java b/compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
similarity index 82%
copy from tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
copy to compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
index 87fb8083b1..b2ebb77c95 100644
--- a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
+++ b/compatible/src/test/java/io/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
@@ -14,15 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seata.rm.tcc.interceptor;
+package io.seata.rm.tcc.interceptor;
 
-import java.io.IOException;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.apache.seata.core.context.RootContext;
+import io.seata.rm.tcc.NormalTccActionImpl;
+import io.seata.rm.tcc.TccParam;
+import io.seata.core.context.RootContext;
 import org.apache.seata.core.exception.TransactionException;
 import org.apache.seata.core.model.BranchStatus;
 import org.apache.seata.core.model.BranchType;
@@ -31,25 +32,17 @@ import org.apache.seata.core.model.Resource;
 import org.apache.seata.core.model.ResourceManager;
 import org.apache.seata.integration.tx.api.util.ProxyUtil;
 import org.apache.seata.rm.DefaultResourceManager;
-import org.apache.seata.rm.tcc.NormalTccActionImpl;
-import org.apache.seata.rm.tcc.TccParam;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-
 public class ProxyUtilsTccTest {
 
     private final String DEFAULT_XID = "default_xid";
 
-    private static NormalTccActionImpl tccAction;
-
-    private static NormalTccActionImpl tccActionProxy;
-
-    AtomicReference<String> branchReference = new AtomicReference<String>();
+    private final AtomicReference<String> branchReference = new AtomicReference<String>();
 
 
-    ResourceManager resourceManager = new ResourceManager() {
+    private final ResourceManager resourceManager = new ResourceManager() {
 
         @Override
         public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException {
@@ -105,11 +98,7 @@ public class ProxyUtilsTccTest {
 
     };
 
-    @BeforeAll
-    public static void init() throws IOException {
-        tccAction = new NormalTccActionImpl();
-        tccActionProxy = ProxyUtil.createProxy(tccAction);
-    }
+    private final NormalTccActionImpl tccActionProxy= ProxyUtil.createProxy(new NormalTccActionImpl());
 
 
     @Test
@@ -118,17 +107,16 @@ public class ProxyUtilsTccTest {
         RootContext.bind(DEFAULT_XID);
 
         TccParam tccParam = new TccParam(1, "abc@163.com");
-        List<String> listB = Arrays.asList("b");
+        List<String> listB = Collections.singletonList("b");
 
         DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
 
-        //when
         String result = tccActionProxy.prepare(null, 0, listB, tccParam);
 
         //then
         Assertions.assertEquals("a", result);
         Assertions.assertNotNull(result);
-        Assertions.assertEquals("normalTccActionForTest", branchReference.get());
+        Assertions.assertEquals("tccActionForCompatibleTest", branchReference.get());
     }
 
     @Test
@@ -137,7 +125,7 @@ public class ProxyUtilsTccTest {
         RootContext.bind(DEFAULT_XID);
 
         TccParam tccParam = new TccParam(1, "abc@163.com");
-        List<String> listB = Arrays.asList("b");
+        List<String> listB = Collections.singletonList("b");
 
         DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
 
diff --git a/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java
new file mode 100644
index 0000000000..b8dc1f9a92
--- /dev/null
+++ b/compatible/src/test/java/io/seata/rm/tcc/interceptor/parser/TccActionInterceptorParserTest.java
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.seata.rm.tcc.interceptor.parser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import io.seata.core.context.RootContext;
+import io.seata.rm.tcc.BranchSessionMock;
+import io.seata.rm.tcc.NestTccAction;
+import io.seata.rm.tcc.NestTccActionImpl;
+import io.seata.rm.tcc.NormalTccActionImpl;
+import io.seata.rm.tcc.TccAction;
+import io.seata.rm.tcc.TccActionImpl;
+import io.seata.tm.api.GlobalTransaction;
+import io.seata.tm.api.GlobalTransactionContext;
+import org.apache.seata.core.exception.TransactionException;
+import org.apache.seata.core.model.BranchType;
+import org.apache.seata.core.model.GlobalStatus;
+import org.apache.seata.core.model.ResourceManager;
+import org.apache.seata.core.model.TransactionManager;
+import org.apache.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler;
+import org.apache.seata.integration.tx.api.interceptor.parser.DefaultInterfaceParser;
+import org.apache.seata.integration.tx.api.util.ProxyUtil;
+import org.apache.seata.rm.DefaultResourceManager;
+import org.apache.seata.rm.tcc.TCCResourceManager;
+import org.apache.seata.tm.TransactionManagerHolder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+
+class TccActionInterceptorParserTest {
+
+    @BeforeAll
+    public static void init() throws IOException {
+        System.setProperty("config.type", "file");
+        System.setProperty("config.file.name", "file.conf");
+        System.setProperty("txServiceGroup", "default_tx_group");
+        System.setProperty("service.vgroupMapping.default_tx_group", "default");
+    }
+
+    @Test
+    void parserInterfaceToProxy() {
+
+        //given
+        TccActionInterceptorParser tccActionInterceptorParser = new TccActionInterceptorParser();
+        NormalTccActionImpl tccAction = new NormalTccActionImpl();
+
+        //when
+        ProxyInvocationHandler proxyInvocationHandler = tccActionInterceptorParser.parserInterfaceToProxy(tccAction, tccAction.getClass().getName());
+
+        //then
+        Assertions.assertNotNull(proxyInvocationHandler);
+
+    }
+
+
+    @Test
+    public void testNestTcc_should_commit() throws Exception {
+        //given
+        RootContext.unbind();
+        DefaultResourceManager.get();
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+        TransactionManagerHolder.set(transactionManager);
+
+        TccActionImpl tccAction = new TccActionImpl();
+        TccAction tccActionProxy =  ProxyUtil.createProxy(tccAction);
+        Assertions.assertNotNull(tccActionProxy);
+
+        NestTccActionImpl nestTccAction = new NestTccActionImpl();
+        nestTccAction.setTccAction(tccActionProxy);
+
+        //when
+        ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+        //then
+        Assertions.assertNotNull(proxyInvocationHandler);
+
+
+        //when
+        NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+        //then
+        Assertions.assertNotNull(nestTccActionProxy);
+
+
+        // transaction commit test
+        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+        try {
+            tx.begin(60000, "testBiz");
+
+            boolean result = nestTccActionProxy.prepare(null, 2);
+
+            Assertions.assertTrue(result);
+
+            if (result) {
+                tx.commit();
+            } else {
+                tx.rollback();
+            }
+        } catch (Exception exx) {
+            tx.rollback();
+            throw exx;
+        }
+
+        Assertions.assertTrue(nestTccAction.isCommit());
+        Assertions.assertTrue(tccAction.isCommit());
+
+    }
+
+
+    @Test
+    public void testNestTcc_should_rollback() throws Exception {
+        //given
+        RootContext.unbind();
+        DefaultResourceManager.get();
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+        TransactionManagerHolder.set(transactionManager);
+
+        TccActionImpl tccAction = new TccActionImpl();
+        TccAction tccActionProxy =  ProxyUtil.createProxy(tccAction);
+        Assertions.assertNotNull(tccActionProxy);
+
+        NestTccActionImpl nestTccAction = new NestTccActionImpl();
+        nestTccAction.setTccAction(tccActionProxy);
+
+        //when
+        ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+        //then
+        Assertions.assertNotNull(proxyInvocationHandler);
+
+
+        //when
+        NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+        //then
+        Assertions.assertNotNull(nestTccActionProxy);
+
+
+        // transaction commit test
+        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+        try {
+            tx.begin(60000, "testBiz");
+
+            boolean result = nestTccActionProxy.prepare(null, 1);
+
+            Assertions.assertFalse(result);
+
+            if (result) {
+                tx.commit();
+            } else {
+                tx.rollback();
+            }
+        } catch (Exception exx) {
+            tx.rollback();
+            throw exx;
+        }
+
+        Assertions.assertFalse(nestTccAction.isCommit());
+        Assertions.assertFalse(tccAction.isCommit());
+
+    }
+
+
+    @Test
+    public void testNestTcc_required_new_should_rollback_commit() throws Exception {
+        //given
+        RootContext.unbind();
+        DefaultResourceManager.get();
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+        TransactionManagerHolder.set(transactionManager);
+
+        TccActionImpl tccAction = new TccActionImpl();
+        TccAction tccActionProxy =  ProxyUtil.createProxy(tccAction);
+        Assertions.assertNotNull(tccActionProxy);
+
+        NestTccActionImpl nestTccAction = new NestTccActionImpl();
+        nestTccAction.setTccAction(tccActionProxy);
+
+        //when
+        ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+        //then
+        Assertions.assertNotNull(proxyInvocationHandler);
+
+        //when
+        NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+        //then
+        Assertions.assertNotNull(nestTccActionProxy);
+
+
+        // transaction commit test
+        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+        try {
+            tx.begin(60000, "testBiz");
+
+            boolean result = nestTccActionProxy.prepareNestRequiredNew(null, 1);
+
+            Assertions.assertFalse(result);
+
+            if (result) {
+                tx.commit();
+            } else {
+                tx.rollback();
+            }
+        } catch (Exception exx) {
+            tx.rollback();
+            throw exx;
+        }
+
+        Assertions.assertTrue(nestTccAction.isCommit());
+        Assertions.assertTrue(tccAction.isCommit());
+
+    }
+
+
+
+    @Test
+    public void testNestTcc_required_new_should_both_commit() throws Exception {
+        //given
+        RootContext.unbind();
+        DefaultResourceManager.get();
+        DefaultResourceManager.mockResourceManager(BranchType.TCC, resourceManager);
+
+        TransactionManagerHolder.set(transactionManager);
+
+        TccActionImpl tccAction = new TccActionImpl();
+        TccAction tccActionProxy =  ProxyUtil.createProxy(tccAction);
+        Assertions.assertNotNull(tccActionProxy);
+
+        NestTccActionImpl nestTccAction = new NestTccActionImpl();
+        nestTccAction.setTccAction(tccActionProxy);
+
+        //when
+        ProxyInvocationHandler proxyInvocationHandler = DefaultInterfaceParser.get().parserInterfaceToProxy(nestTccAction, nestTccAction.getClass().getName());
+
+        //then
+        Assertions.assertNotNull(proxyInvocationHandler);
+
+        //when
+        NestTccAction nestTccActionProxy = ProxyUtil.createProxy(nestTccAction);
+        //then
+        Assertions.assertNotNull(nestTccActionProxy);
+
+
+        // transaction commit test
+        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
+
+        try {
+            tx.begin(60000, "testBiz");
+
+            boolean result = nestTccActionProxy.prepareNestRequiredNew(null, 2);
+
+            Assertions.assertTrue(result);
+
+            if (result) {
+                tx.commit();
+            } else {
+                tx.rollback();
+            }
+        } catch (Exception exx) {
+            tx.rollback();
+            throw exx;
+        }
+
+        Assertions.assertTrue(nestTccAction.isCommit());
+        Assertions.assertTrue(tccAction.isCommit());
+
+    }
+
+
+
+    private static Map<String, List<BranchSessionMock>> applicationDataMap = new ConcurrentHashMap<>();
+
+
+    private static TransactionManager transactionManager = new TransactionManager() {
+        @Override
+        public String begin(String applicationId, String transactionServiceGroup, String name, int timeout) throws TransactionException {
+            return UUID.randomUUID().toString();
+        }
+
+        @Override
+        public GlobalStatus commit(String xid) throws TransactionException {
+            commitAll(xid);
+            return GlobalStatus.Committed;
+        }
+
+        @Override
+        public GlobalStatus rollback(String xid) throws TransactionException {
+
+            rollbackAll(xid);
+
+            return GlobalStatus.Rollbacked;
+        }
+
+        @Override
+        public GlobalStatus getStatus(String xid) throws TransactionException {
+            return GlobalStatus.Begin;
+        }
+
+        @Override
+        public GlobalStatus globalReport(String xid, GlobalStatus globalStatus) throws TransactionException {
+            return globalStatus;
+        }
+    };
+
+
+    private static ResourceManager resourceManager = new TCCResourceManager() {
+
+        @Override
+        public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException {
+
+            long branchId = System.currentTimeMillis();
+
+            List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+            BranchSessionMock branchSessionMock = new BranchSessionMock();
+            branchSessionMock.setXid(xid);
+            branchSessionMock.setBranchType(branchType);
+            branchSessionMock.setResourceId(resourceId);
+            branchSessionMock.setApplicationData(applicationData);
+            branchSessionMock.setBranchId(branchId);
+
+            branches.add(branchSessionMock);
+
+            return branchId;
+        }
+    };
+
+    public static void commitAll(String xid) throws TransactionException {
+
+        List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+        for (BranchSessionMock branch : branches) {
+            resourceManager.branchCommit(branch.getBranchType(), branch.getXid(), branch.getBranchId(), branch.getResourceId(), branch.getApplicationData());
+        }
+    }
+
+    public static void rollbackAll(String xid) throws TransactionException {
+
+        List<BranchSessionMock> branches = applicationDataMap.computeIfAbsent(xid, s -> new ArrayList<>());
+        for (BranchSessionMock branch : branches) {
+            resourceManager.branchRollback(branch.getBranchType(), branch.getXid(), branch.getBranchId(), branch.getResourceId(), branch.getApplicationData());
+        }
+    }
+
+}
diff --git a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java b/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java
deleted file mode 100644
index a68010fa7d..0000000000
--- a/integration-tx-api/src/main/java/org/apache/seata/integration/tx/api/annotation/BusinessActionContextParameterDesc.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.seata.integration.tx.api.annotation;
-
-import java.lang.annotation.Annotation;
-
-import org.apache.seata.common.util.StringUtils;
-import org.apache.seata.rm.tcc.api.BusinessActionContextParameter;
-
-
-public class BusinessActionContextParameterDesc {
-    private String paramName;
-    private int index;
-    private boolean isParamInProperty;
-
-    private BusinessActionContextParameterDesc() {
-    }
-
-    public static BusinessActionContextParameterDesc createFromBusinessActionContextParameter(Annotation annotation) {
-        if (annotation == null) {
-            return null;
-        }
-        BusinessActionContextParameterDesc businessActionContextParameterDesc = null;
-        if (annotation instanceof BusinessActionContextParameter) {
-            businessActionContextParameterDesc = new BusinessActionContextParameterDesc();
-            BusinessActionContextParameter businessActionContextParameter = (BusinessActionContextParameter) annotation;
-            businessActionContextParameterDesc.setIndex(businessActionContextParameter.index());
-            businessActionContextParameterDesc.setParamInProperty(businessActionContextParameter.isParamInProperty());
-            businessActionContextParameterDesc.setParamName(StringUtils.isNotBlank(businessActionContextParameter.paramName()) ? businessActionContextParameter.paramName() : businessActionContextParameter.value());
-        }
-        return businessActionContextParameterDesc;
-    }
-
-    public String getParamName() {
-        return paramName;
-    }
-
-    public void setParamName(String paramName) {
-        this.paramName = paramName;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public void setIndex(int index) {
-        this.index = index;
-    }
-
-    public boolean isParamInProperty() {
-        return isParamInProperty;
-    }
-
-    public void setParamInProperty(boolean paramInProperty) {
-        isParamInProperty = paramInProperty;
-    }
-}
diff --git a/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java b/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
index ca485f1c9b..f2a37ef56e 100644
--- a/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
+++ b/integration-tx-api/src/main/java/org/apache/seata/rm/tcc/api/BusinessActionContextParameter.java
@@ -26,7 +26,7 @@ import java.lang.annotation.Target;
  * <p>
  * add this annotation on the parameters of the try method, and the parameters will be passed to the action context
  *
- * @see org.apache.seata.spring.interceptor.ActionContextUtil
+ * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.PARAMETER, ElementType.FIELD})
@@ -36,7 +36,7 @@ public @interface BusinessActionContextParameter {
      * parameter's name. Synonym for {@link #paramName()}.
      *
      * @return the name of the param or field
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+     * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
      */
     String value() default "";
 
@@ -44,7 +44,7 @@ public @interface BusinessActionContextParameter {
      * parameter's name. Synonym for {@link #value()}.
      *
      * @return the name of the param or field
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getParamNameFromAnnotation
+     * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getParamNameFromAnnotation
      */
     String paramName() default "";
 
@@ -61,7 +61,7 @@ public @interface BusinessActionContextParameter {
      * Specify the index of the parameter in the List
      *
      * @return the index of the List
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#getByIndex
+     * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#getByIndex
      */
     int index() default -1;
 
@@ -70,8 +70,8 @@ public @interface BusinessActionContextParameter {
      * if {@code index >= 0}, the object get from the List and then do get the parameter from the property of the object
      *
      * @return the boolean
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
-     * @see org.apache.seata.spring.interceptor.ActionContextUtil#fetchContextFromObject
+     * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#loadParamByAnnotationAndPutToContext
+     * @see org.apache.seata.integration.tx.api.interceptor.ActionContextUtil#fetchContextFromObject
      */
     boolean isParamInProperty() default false;
 }
diff --git a/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java b/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
index 06afa1d7b1..448167439a 100644
--- a/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
+++ b/spring/src/main/java/org/apache/seata/spring/tcc/TccAnnotationProcessor.java
@@ -37,8 +37,9 @@ import java.util.Set;
 
 /**
  * An annotation adapter for TCC
- *
+ * Deprecated: Tcc advice move to rm side
  */
+@Deprecated
 public class TccAnnotationProcessor implements BeanPostProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(TccAnnotationProcessor.class);
 
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
index 82a7d6a7dc..acf84663c1 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/interceptor/TccActionInterceptorHandler.java
@@ -16,6 +16,7 @@
  */
 package org.apache.seata.rm.tcc.interceptor;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
@@ -53,7 +54,7 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
     private Set<String> methodsToProxy;
     protected Object targetBean;
 
-    protected Map<Method, TwoPhaseBusinessAction> parseAnnotationCache = new ConcurrentHashMap<>();
+    protected Map<Method, Annotation> parseAnnotationCache = new ConcurrentHashMap<>();
 
     public TccActionInterceptorHandler(Object targetBean, Set<String> methodsToProxy) {
         this.targetBean = targetBean;
@@ -67,7 +68,7 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
             return invocation.proceed();
         }
         Method method = invocation.getMethod();
-        TwoPhaseBusinessAction businessAction = parseAnnotation(method);
+        Annotation businessAction = parseAnnotation(method);
 
         //try method
         if (businessAction != null) {
@@ -76,28 +77,17 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
             //save the previous branchType
             BranchType previousBranchType = RootContext.getBranchType();
             //if not TCC, bind TCC branchType
-            if (BranchType.TCC != previousBranchType) {
-                RootContext.bindBranchType(BranchType.TCC);
+            if (getBranchType() != previousBranchType) {
+                RootContext.bindBranchType(getBranchType());
             }
             try {
-                TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
-                businessActionParam.setActionName(businessAction.name());
-                businessActionParam.setDelayReport(businessAction.isDelayReport());
-                businessActionParam.setUseCommonFence(businessAction.useTCCFence());
-                businessActionParam.setBranchType(BranchType.TCC);
-                Map<String, Object> businessActionContextMap = new HashMap<>(4);
-                //the phase two method name
-                businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
-                businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
-                businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
-                businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
-                businessActionParam.setBusinessActionContext(businessActionContextMap);
+                TwoPhaseBusinessActionParam businessActionParam = createTwoPhaseBusinessActionParam(businessAction);
                 //Handler the TCC Aspect, and return the business result
                 return actionInterceptorHandler.proceed(method, invocation.getArguments(), xid, businessActionParam,
                         invocation::proceed);
             } finally {
                 //if not TCC, unbind branchType
-                if (BranchType.TCC != previousBranchType) {
+                if (getBranchType() != previousBranchType) {
                     RootContext.unbindBranchType();
                 }
                 //MDC remove branchId
@@ -109,19 +99,19 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
         return invocation.proceed();
     }
 
-    private TwoPhaseBusinessAction parseAnnotation(Method methodKey) throws NoSuchMethodException {
-        TwoPhaseBusinessAction result = parseAnnotationCache.computeIfAbsent(methodKey, method -> {
-            TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
-            if (businessAction == null && targetBean.getClass() != null) {
+    private Annotation parseAnnotation(Method methodKey) throws NoSuchMethodException {
+        Annotation result = parseAnnotationCache.computeIfAbsent(methodKey, method -> {
+            Annotation twoPhaseBusinessAction = method.getAnnotation(getAnnotationClass());
+            if (twoPhaseBusinessAction == null && targetBean.getClass() != null) {
                 Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass());
                 if (interfaceClasses != null) {
                     for (Class<?> interClass : interfaceClasses) {
                         try {
                             Method m = interClass.getMethod(method.getName(), method.getParameterTypes());
-                            businessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
-                            if (businessAction != null) {
+                            twoPhaseBusinessAction = m.getAnnotation(getAnnotationClass());
+                            if (twoPhaseBusinessAction != null) {
                                 // init common fence clean task if enable useTccFence
-                                initCommonFenceCleanTask(businessAction);
+                                initCommonFenceCleanTask(twoPhaseBusinessAction);
                                 break;
                             }
                         } catch (NoSuchMethodException e) {
@@ -130,22 +120,55 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
                     }
                 }
             }
-            return businessAction;
+            return twoPhaseBusinessAction;
         });
         return result;
     }
 
+    protected TwoPhaseBusinessActionParam createTwoPhaseBusinessActionParam(Annotation annotation) {
+        TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+        TwoPhaseBusinessActionParam businessActionParam = new TwoPhaseBusinessActionParam();
+        businessActionParam.setActionName(businessAction.name());
+        businessActionParam.setDelayReport(businessAction.isDelayReport());
+        businessActionParam.setUseCommonFence(businessAction.useTCCFence());
+        businessActionParam.setBranchType(getBranchType());
+        Map<String, Object> businessActionContextMap = new HashMap<>(4);
+        //the phase two method name
+        businessActionContextMap.put(Constants.COMMIT_METHOD, businessAction.commitMethod());
+        businessActionContextMap.put(Constants.ROLLBACK_METHOD, businessAction.rollbackMethod());
+        businessActionContextMap.put(Constants.ACTION_NAME, businessAction.name());
+        businessActionContextMap.put(Constants.USE_COMMON_FENCE, businessAction.useTCCFence());
+        businessActionParam.setBusinessActionContext(businessActionContextMap);
+        return businessActionParam;
+    }
+
+    protected boolean parserCommonFenceConfig(Annotation annotation) {
+        if (annotation == null) {
+            return false;
+        }
+        TwoPhaseBusinessAction businessAction = (TwoPhaseBusinessAction) annotation;
+        return businessAction.useTCCFence();
+    }
+
+    protected BranchType getBranchType() {
+        return BranchType.TCC;
+    }
+
+    protected Class<? extends Annotation> getAnnotationClass() {
+        return TwoPhaseBusinessAction.class;
+    }
+
     /**
      * init common fence clean task if enable useTccFence
      *
      * @param twoPhaseBusinessAction the twoPhaseBusinessAction
      */
-    private void initCommonFenceCleanTask(TwoPhaseBusinessAction twoPhaseBusinessAction) {
+    private void initCommonFenceCleanTask(Annotation twoPhaseBusinessAction) {
         CommonFenceConfig commonFenceConfig = (CommonFenceConfig) ObjectHolder.INSTANCE.getObject(BEAN_NAME_SPRING_FENCE_CONFIG);
         if (commonFenceConfig == null || commonFenceConfig.getInitialized().get()) {
             return;
         }
-        if (twoPhaseBusinessAction != null && twoPhaseBusinessAction.useTCCFence()) {
+        if (twoPhaseBusinessAction != null && parserCommonFenceConfig(twoPhaseBusinessAction)) {
             if (commonFenceConfig.getInitialized().compareAndSet(false, true)) {
                 // init common fence clean task if enable useTccFence
                 commonFenceConfig.init();
diff --git a/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java b/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
index d95e54e9d3..0d72824bf9 100644
--- a/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
+++ b/tcc/src/main/java/org/apache/seata/rm/tcc/resource/parser/TccRegisterResourceParser.java
@@ -40,17 +40,18 @@ public class TccRegisterResourceParser implements RegisterResourceParser {
         try {
             //service bean, registry resource
             Class<?> serviceClass = target.getClass();
-            this.executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
+            executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
             Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
             for (Class<?> interClass : interfaceClasses) {
-                this.executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
+                executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
             }
         } catch (Throwable t) {
             throw new FrameworkException(t, "parser remoting service error");
         }
     }
 
-    private void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
+
+    protected void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
         for (Method m : methods) {
             TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
             if (twoPhaseBusinessAction != null) {
@@ -71,9 +72,9 @@ public class TccRegisterResourceParser implements RegisterResourceParser {
                 tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
                 tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
                 // set phase two method's keys
-                tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
+                tccResource.setPhaseTwoCommitKeys(getTwoPhaseArgs(tccResource.getCommitMethod(),
                         twoPhaseBusinessAction.commitArgsClasses()));
-                tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
+                tccResource.setPhaseTwoRollbackKeys(getTwoPhaseArgs(tccResource.getRollbackMethod(),
                         twoPhaseBusinessAction.rollbackArgsClasses()));
                 //registry tcc resource
                 DefaultResourceManager.get().registerResource(tccResource);
diff --git a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
index 87fb8083b1..5149377c4d 100644
--- a/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
+++ b/tcc/src/test/java/org/apache/seata/rm/tcc/interceptor/ProxyUtilsTccTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.seata.rm.tcc.interceptor;
 
-import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -34,7 +33,6 @@ import org.apache.seata.rm.DefaultResourceManager;
 import org.apache.seata.rm.tcc.NormalTccActionImpl;
 import org.apache.seata.rm.tcc.TccParam;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 
@@ -42,10 +40,6 @@ public class ProxyUtilsTccTest {
 
     private final String DEFAULT_XID = "default_xid";
 
-    private static NormalTccActionImpl tccAction;
-
-    private static NormalTccActionImpl tccActionProxy;
-
     AtomicReference<String> branchReference = new AtomicReference<String>();
 
 
@@ -105,11 +99,7 @@ public class ProxyUtilsTccTest {
 
     };
 
-    @BeforeAll
-    public static void init() throws IOException {
-        tccAction = new NormalTccActionImpl();
-        tccActionProxy = ProxyUtil.createProxy(tccAction);
-    }
+    private final NormalTccActionImpl tccActionProxy= ProxyUtil.createProxy(new NormalTccActionImpl());
 
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org