-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
optimize: compatible with integration-tx-api module and spring module (…
- Loading branch information
1 parent
4006df1
commit 65610d0
Showing
17 changed files
with
906 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
compatible/src/main/java/io/seata/common/LockStrategyMode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* 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.common; | ||
|
||
public enum LockStrategyMode { | ||
/** | ||
* Optimistic lock mode is recommended when resources are not reused in the current global transaction. | ||
*/ | ||
OPTIMISTIC, | ||
/** | ||
* Pessimistic lock mode is recommended when there may be repeated use of the same resource in a global transaction. | ||
*/ | ||
PESSIMISTIC | ||
} |
170 changes: 170 additions & 0 deletions
170
compatible/src/main/java/io/seata/integration/tx/api/interceptor/ActionContextUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
* 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.integration.tx.api.interceptor; | ||
|
||
import io.seata.rm.tcc.api.BusinessActionContext; | ||
import io.seata.rm.tcc.api.BusinessActionContextParameter; | ||
import org.apache.seata.common.util.CollectionUtils; | ||
import org.apache.seata.common.util.StringUtils; | ||
import org.apache.seata.rm.tcc.api.ParamType; | ||
|
||
import javax.annotation.Nonnull; | ||
import javax.annotation.Nullable; | ||
import java.util.Map; | ||
|
||
import static org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.getByIndex; | ||
|
||
/** | ||
* Extracting TCC Context from Method | ||
*/ | ||
public final class ActionContextUtil { | ||
|
||
private ActionContextUtil() { | ||
} | ||
|
||
/** | ||
* Extracting context data from parameters | ||
* | ||
* @param targetParam the target param | ||
* @return map the context | ||
*/ | ||
public static Map<String, Object> fetchContextFromObject(@Nonnull Object targetParam) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.fetchContextFromObject(targetParam); | ||
} | ||
|
||
/** | ||
* load param by the config of annotation, and then put into the action context | ||
* | ||
* @param paramType the param type, 'param' or 'field' | ||
* @param paramName the param name | ||
* @param paramValue the param value | ||
* @param annotation the annotation on the param or field | ||
* @param actionContext the action context | ||
*/ | ||
public static void loadParamByAnnotationAndPutToContext(@Nonnull final ParamType paramType, @Nonnull String paramName, Object paramValue, | ||
@Nonnull final BusinessActionContextParameter annotation, @Nonnull final Map<String, Object> actionContext) { | ||
if (paramValue == null) { | ||
return; | ||
} | ||
|
||
// If {@code index >= 0}, get by index from the list param or field | ||
int index = annotation.index(); | ||
if (index >= 0) { | ||
paramValue = getByIndex(paramType, paramName, paramValue, index); | ||
if (paramValue == null) { | ||
return; | ||
} | ||
} | ||
|
||
// if {@code isParamInProperty == true}, fetch context from paramValue | ||
if (annotation.isParamInProperty()) { | ||
Map<String, Object> paramContext = fetchContextFromObject(paramValue); | ||
if (CollectionUtils.isNotEmpty(paramContext)) { | ||
actionContext.putAll(paramContext); | ||
} | ||
} else { | ||
// get param name from the annotation | ||
String paramNameFromAnnotation = getParamNameFromAnnotation(annotation); | ||
if (StringUtils.isNotBlank(paramNameFromAnnotation)) { | ||
paramName = paramNameFromAnnotation; | ||
} | ||
putActionContextWithoutHandle(actionContext, paramName, paramValue); | ||
} | ||
} | ||
|
||
|
||
public static String getParamNameFromAnnotation(@Nonnull BusinessActionContextParameter annotation) { | ||
String paramName = annotation.paramName(); | ||
if (StringUtils.isBlank(paramName)) { | ||
paramName = annotation.value(); | ||
} | ||
return paramName; | ||
} | ||
|
||
/** | ||
* put the action context after handle | ||
* | ||
* @param actionContext the action context | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContext(Map<String, Object> actionContext, String key, Object value) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContext(actionContext, key, value); | ||
} | ||
|
||
/** | ||
* put the action context after handle | ||
* | ||
* @param actionContext the action context | ||
* @param actionContextMap the actionContextMap | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContext(Map<String, Object> actionContext, @Nonnull Map<String, Object> actionContextMap) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContext(actionContext, actionContextMap); | ||
} | ||
|
||
/** | ||
* put the action context without handle | ||
* | ||
* @param actionContext the action context | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContextWithoutHandle(@Nonnull final Map<String, Object> actionContext, String key, Object value) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContextWithoutHandle(actionContext, key, value); | ||
} | ||
|
||
/** | ||
* put the action context without handle | ||
* | ||
* @param actionContext the action context | ||
* @param actionContextMap the actionContextMap | ||
* @return the action context is changed | ||
*/ | ||
public static boolean putActionContextWithoutHandle(Map<String, Object> actionContext, @Nonnull Map<String, Object> actionContextMap) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.putActionContextWithoutHandle(actionContext, actionContextMap); | ||
} | ||
|
||
/** | ||
* Handle the action context. | ||
* It is convenient to convert type in phase 2. | ||
* | ||
* @param actionContext the action context | ||
* @return the action context or JSON string | ||
* @see #convertActionContext(String, Object, Class) | ||
* @see BusinessActionContext#getActionContext(String, Class) | ||
*/ | ||
public static Object handleActionContext(@Nonnull Object actionContext) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.handleActionContext(actionContext); | ||
} | ||
|
||
/** | ||
* Convert action context | ||
* | ||
* @param key the actionContext's key | ||
* @param value the actionContext's value | ||
* @param targetClazz the target class | ||
* @param <T> the target type | ||
* @return the action context of the target type | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
public static <T> T convertActionContext(String key, @Nullable Object value, @Nonnull Class<T> targetClazz) { | ||
return org.apache.seata.integration.tx.api.interceptor.ActionContextUtil.convertActionContext(key, value, targetClazz); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
...tible/src/main/java/io/seata/integration/tx/api/interceptor/ActionInterceptorHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.integration.tx.api.interceptor; | ||
|
||
import io.seata.rm.tcc.api.BusinessActionContextParameter; | ||
import org.apache.seata.rm.tcc.api.ParamType; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Method; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* Handler the Tx Participant Aspect : Setting Context, Creating Branch Record | ||
*/ | ||
public class ActionInterceptorHandler extends org.apache.seata.integration.tx.api.interceptor.ActionInterceptorHandler { | ||
|
||
|
||
/** | ||
* Extracting context data from parameters, add them to the context | ||
* | ||
* @param method the method | ||
* @param arguments the arguments | ||
* @return the context | ||
*/ | ||
@Override | ||
protected Map<String, Object> fetchActionRequestContext(Method method, Object[] arguments) { | ||
Map<String, Object> context = new HashMap<>(8); | ||
|
||
Annotation[][] parameterAnnotations = method.getParameterAnnotations(); | ||
for (int i = 0; i < parameterAnnotations.length; i++) { | ||
for (int j = 0; j < parameterAnnotations[i].length; j++) { | ||
if (parameterAnnotations[i][j] instanceof org.apache.seata.rm.tcc.api.BusinessActionContextParameter) { | ||
// get annotation | ||
BusinessActionContextParameter annotation = (BusinessActionContextParameter) parameterAnnotations[i][j]; | ||
if (arguments[i] == null) { | ||
throw new IllegalArgumentException("@BusinessActionContextParameter 's params can not null"); | ||
} | ||
|
||
// get param | ||
Object paramObject = arguments[i]; | ||
if (paramObject == null) { | ||
continue; | ||
} | ||
|
||
// load param by the config of annotation, and then put into the context | ||
ActionContextUtil.loadParamByAnnotationAndPutToContext(ParamType.PARAM, "", paramObject, annotation, context); | ||
} | ||
} | ||
} | ||
return context; | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
...o/seata/integration/tx/api/interceptor/handler/GlobalTransactionalInterceptorHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* 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.integration.tx.api.interceptor.handler; | ||
|
||
import io.seata.spring.annotation.GlobalLock; | ||
import io.seata.spring.annotation.GlobalTransactional; | ||
import io.seata.tm.api.FailureHandler; | ||
import org.apache.seata.core.model.GlobalLockConfig; | ||
import org.apache.seata.integration.tx.api.annotation.AspectTransactional; | ||
import org.apache.seata.integration.tx.api.interceptor.InvocationWrapper; | ||
import org.apache.seata.integration.tx.api.util.ClassUtils; | ||
import org.apache.seata.rm.GlobalLockExecutor; | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.Set; | ||
|
||
/** | ||
* The type Global transactional interceptor handler. | ||
*/ | ||
public class GlobalTransactionalInterceptorHandler extends org.apache.seata.integration.tx.api.interceptor.handler.GlobalTransactionalInterceptorHandler { | ||
|
||
|
||
public GlobalTransactionalInterceptorHandler(FailureHandler failureHandler, Set<String> methodsToProxy) { | ||
super(failureHandler, methodsToProxy); | ||
} | ||
|
||
public GlobalTransactionalInterceptorHandler(FailureHandler failureHandler, Set<String> methodsToProxy, AspectTransactional aspectTransactional) { | ||
super(failureHandler, methodsToProxy, aspectTransactional); | ||
} | ||
|
||
@Override | ||
protected Object doInvoke(InvocationWrapper invocation) throws Throwable { | ||
Class<?> targetClass = invocation.getTarget().getClass(); | ||
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass); | ||
if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) { | ||
final GlobalTransactional globalTransactionalAnnotation = getAnnotation(specificMethod, targetClass, GlobalTransactional.class); | ||
final GlobalLock globalLockAnnotation = getAnnotation(specificMethod, targetClass, GlobalLock.class); | ||
boolean localDisable = disable || (ATOMIC_DEGRADE_CHECK.get() && degradeNum >= degradeCheckAllowTimes); | ||
if (!localDisable) { | ||
if (globalTransactionalAnnotation != null || this.aspectTransactional != null) { | ||
AspectTransactional transactional; | ||
if (globalTransactionalAnnotation != null) { | ||
transactional = new AspectTransactional(globalTransactionalAnnotation.timeoutMills(), | ||
globalTransactionalAnnotation.name(), globalTransactionalAnnotation.rollbackFor(), | ||
globalTransactionalAnnotation.rollbackForClassName(), | ||
globalTransactionalAnnotation.noRollbackFor(), | ||
globalTransactionalAnnotation.noRollbackForClassName(), | ||
org.apache.seata.tm.api.transaction.Propagation.valueOf(globalTransactionalAnnotation.propagation().name()), | ||
globalTransactionalAnnotation.lockRetryInterval(), | ||
globalTransactionalAnnotation.lockRetryTimes(), | ||
org.apache.seata.common.LockStrategyMode.valueOf(globalTransactionalAnnotation.lockStrategyMode().name())); | ||
} else { | ||
transactional = this.aspectTransactional; | ||
} | ||
return handleGlobalTransaction(invocation, transactional); | ||
} else if (globalLockAnnotation != null) { | ||
return handleGlobalLock(invocation, globalLockAnnotation); | ||
} | ||
} | ||
} | ||
return invocation.proceed(); | ||
} | ||
|
||
|
||
private Object handleGlobalLock(final InvocationWrapper methodInvocation, final GlobalLock globalLockAnno) throws Throwable { | ||
return globalLockTemplate.execute(new GlobalLockExecutor() { | ||
@Override | ||
public Object execute() throws Throwable { | ||
return methodInvocation.proceed(); | ||
} | ||
|
||
@Override | ||
public GlobalLockConfig getGlobalLockConfig() { | ||
GlobalLockConfig config = new GlobalLockConfig(); | ||
config.setLockRetryInterval(globalLockAnno.lockRetryInterval()); | ||
config.setLockRetryTimes(globalLockAnno.lockRetryTimes()); | ||
return config; | ||
} | ||
}); | ||
} | ||
} |
Oops, something went wrong.